I don't suppose there's a way to extend types...

BlitzMax Forums/BlitzMax Beginners Area/I don't suppose there's a way to extend types...

sswift(Posted 2006) [#1]
Without "extending" them?

Here's the problem:

Mark's TList type doesn't have a method to swap two links in the list. I'd like to add a method to do this. I do not want to change the source to max however because that would be bad and get overwritten, etc.

But I also have used the TList type throughought my code. If I were to make a new type using the Extends keyword to extend the list type, I'd have to go through all of my code and change it to use the new list type name instead, and I might miss some instances in one of my source files. Anyways I'd just rather not have to do this. It might be possible to do right now, but I'm thinking about a much bigger project what one might do in that case.

So the ideal thing would be to have the ability to add methods to a type without actually making a new type. Like, use the same type name elsewhere in the code, add additional fields, and methods, and functions to that, and they are magically included in the original type.

Cue people telling me that's not how OOP works and that convenience is the thing we sacrifice to the OOP god.


Dreamora(Posted 2006) [#2]
clone the module to an own one and make sure you import that instead of brl.linkedlist

That way it shouldn't be a problem.

There is no other way unless you want to use the regular extend way I fear.


FlameDuck(Posted 2006) [#3]
If I were to make a new type using the Extends keyword to extend the list type, I'd have to go through all of my code and change it to use the new list type name instead
No you won't. The old TList will still work as usual (as opposed to what you're suggesting).

Like, use the same type name elsewhere in the code, add additional fields, and methods, and functions to that, and they are magically included in the original type.
This might have worked in a script / interpreted language like Python (but it doesn't), or in a late bind language (like Java or C#, but it doesn't) but not in a early bind compiled language like BlitzMAX. Each object must have a well defined interface at link time.

So the ideal thing would be to have the ability to add methods to a type without actually making a new type.
Why would that be ideal? So you instance 50 lists of various objects. Then you decide you want a swaplinks function. Now the compiler at run-time has to go through every list in memory swapping out data structures and interfaces on the go, causeing all sorts of havok and wierd bugs, as things that at one time assumed one interface, now suddenly has another?

Cue people telling me that's not how OOP works and that convenience is the thing we sacrifice to the OOP god.
Convenience is what we get from OO, not what we sacrifice. Make your peace with spagetti code, you won't be needing it anymore.


skidracer(Posted 2006) [#4]
Yes you can extend TList and not have to change anything in your source, but are you really using that many "TList" references, an extended Type is no slower so you should probably get over your fears and start use TSwiftLists, they will automatically inherit any mods made to brl.LinkedList.Tlist....

Anyway, here is a version of TList extended with dreamora's version of Reverse to illustrate how you can replace TList with your own TList

Strict

Type TList Extends brl.LinkedList.TList
	Method Reverse()
		Local temp:TLink
		Local result:TList	= New TList
		
		Local pLink:TLink= _head
		Local ppLink:TLink
		
		Print "dreamoras tlist"
		
		' Let iterate point to tail
		pLink = _head._pred
		
		ppLink	= pLink._pred
		
		result._head._succ			= pLink
		result._head._succ._pred	= result._head
		
		result._head._pred			= firstlink()
		result._head._pred._succ	= result._head
		
		temp	= pLink
		pLink	= ppLink
		ppLink	= pLink._pred
		
		While pLink._value <> pLink			
			temp._succ	= pLink
			pLink._pred	= temp
			
			temp	= temp._succ
			
			pLink	= ppLink
			ppLink	= ppLink._pred
		Wend
		
		swap result
		
	End Method
End Type
 
Local l:TList=New TList
l.AddLast "one"
l.AddLast "two"
l.AddLast "three"
l.Reverse
For Local a$=EachIn l
 Print a$
Next
Print "done"



sswift(Posted 2006) [#5]
"No you won't. The old TList will still work as usual (as opposed to what you're suggesting)."

Yes, but I won't be able to use the new functionality unless I change all the types.


"Now the compiler at run-time has to go through every list in memory swapping out data structures and interfaces on the go, causeing all sorts of havok and wierd bugs, as things that at one time assumed one interface, now suddenly has another?"

If I could write a program to go through the source file and copy all the instances of a type into a single type at the start of the program before compiling it, then the compiler could too.

You're talking about something much more complicated. Maybe types in a function overriding a global type or or something. I don't even know if Max can do those, but I've never used them.


"Convenience is what we get from OO, not what we sacrifice."

I beg to differ. It took me a week to write my sprite system in BlitzPlus. It took me a month to do it in Max. And even though I am now familiar with the basic concepts behind OOP it still takes me a lot longer to design pretty types with functions and methods in them.

For example with procedural programming:
"Hmm... I need a seletor which has four sprites that rotate around one in the middle. I'll just make an array of sprites and create them and voila done."

With OOP:

"Hmm... I need a seelector which has four sprites that rotate around one in the middle... I guess I should have a global array in my type, but what if I want to select multiple objects? Maybe I should have a field array? I guess I need a create function now... Should I have the create function call a New method, or just have a new method? If I just have a new function I can't pass parameters in the future. But a new method isn't neccessary if I'm never going to allocate new selectors with ThisSelector = New Selector. Hm.... Well crap I'm making this more complicated than I need to now cause I really only needed a single selection box, and I don't think I will need to select multiple items. This OOP crap is encouraging me to overengineer everything! So throw out all that crap for allowing multiple selectors and go back to the single global in the type... Now I need to make a function to free the selectior... No wait, I don't need to free the selector, why am I bothering with that. I just need to create the seelctor and hide or show it as needed there's no reason to be creating and freeing it constantly. But I'd have done that in the first place if not for this stupid OOP once again encouraging me to overengineer stuff! Curse you OOP!"


sswift(Posted 2006) [#6]
Skid:
Thanks. There's another thing that concerns me now though, and that's that if I do that, then other libs I use that expect tlist to behave a certain way might not like it if for example, I override the reverselist. They might EXPECT a new list to be created. I don't know why they would or how that woudl affect them, but who knows. Just something elseto be concerned about.

Can I make a type that works wirh EachIn and returns links instead of objects? Cause I'm thinking of taking Mark up on his suggestion of making my own list type that behaves the way I think it should.

I probably shouldn't even explore that option though. It would make my life much easier but take a ton of time I don't have to reimplement linked lists.


sswift(Posted 2006) [#7]
Argh, see? There I go again. This whole discussion is completely unneccessary and I'm even considering something as wasteful as making a new list type. I don't need to extend TList. All I want is the abiltiy to swap two fruit in my fruit list and I already put that functionality in the function. I don't NEED to make it pretty by adding it to TList so I don't have to look at the code!

See, this is the true evil of OOP. It's a TIME SINK!


skidracer(Posted 2006) [#8]
Yeh, that trick is really only going to work in application / global scope, once you define a TList in a third party module I'm thinking the compiler will complain about not knowing which one to use when compiling applications....

I would encourage you also to implement a TFastList, you're going to get major speed ups if you do it properly that will resolve this issue of wanting to continue relations with TList in any shape or form.

And yes the time sink rule applies until your project grows beyond a certain size, then OOP is more like using an architect when building a house.

Expecting to learn best OOP practices from these forums is possibly the other problem I have with your current approach. If you want to program like God you're going to need some decent books for the big picture.


FlameDuck(Posted 2006) [#9]
It took me a week to write my sprite system in BlitzPlus. It took me a month to do it in Max.
That's not a matter of procedural vs. object oriented paradigms, but rather a case of Fred Brooks "Second System Syndrome" - The second system an engineer designs is the most dangerous system he will ever design, since it will be disastrously overdesigned.

Which going by your opening statements, is exactly what's happening here.

If you want to program like God you're going to need some decent books for the big picture.
And if you want a list, I refer you to our previous discussion on this topic.


H&K(Posted 2006) [#10]
God programs in Forth.


FlameDuck(Posted 2006) [#11]
Surely he would program in FORTRAN, COBOL or LISP? (Depending on which kind of program he was writting at the time).