some max OO help please.

BlitzMax Forums/BlitzMax Beginners Area/some max OO help please.

OK this is probably a dumb question but, I wanted to wrap TSound by adding some extra useful functions and properties to it, but I still wanted my new type to work exactly the same, and with the same functions as TSound (e.g. PlaySound etc) - so I started with this:

Type ccSound Extends TSound
	Field test:ccSound
	
	Method LoadSample:ccSound(ThePath$, LoopFlag%)
		test = LoadSound(ThePath$, Loopflag)
		If Not Self Then
	    	ccRunTimeError ("Error loading sample "+ThePath$)
		End
		Else 
    		Return Self			
	  	EndIf		
	EndMethod
EndType


This line "test = LoadSound(ThePath$, Loopflag)" produces the following compile error: "unable to convert from Tsound to ccSound".

Actually originally I didn't have "test", I just put "self = LoadSound(ThePath$, Loopflag)" but this generates the following compile error: "expression must be a variable".

Well I understand that TSound and my ccSound are not the same, but I thought that as ccSound is inherited from TSound, self would be OK, but it isn't. I guess that all the sound functions would also fail with ccSound passed in as well as it isn't able to typecast ccSound as TSound, am I right?

Is the way to solve this to craply have a Field within the ccSound type called TheSound:TSound, and assign my LoadSound to that and then whenever I call any sound functions do it like this:

MySound:ccSound
'pretend I've loaded now
PlaySound(MySound.TheSound)


Thanks in advance, hope this makes sense!

ccSound(loadsound(...)) should work, not?
You need to manually typecast between objects.

oh yeah cool, that's how I typecase in Delphi. Thing is this

self = ccSound(LoadSound(ThePath$, Loopflag))

still gives the "expression must be a variable" error. What's that about then? I guess you can't reassign/set self within itself! Can only New set Self?

[edit]whoa, If I make a TSound variable called X and then call X.Load("blah.wav"), Load returns a TSound pointer, but does it NOT set X to point to the returned pointer? Do I need to go X = X.Load("blah.wav")? In which case I can change my code in the first post to return a ccSound pointer and just do MySound = MySound.LoadSample("foo") which is pretty crap as I'm converting a standalone global function that I could call as MySound = ccLoadSample("foo"). I was trying to avoid tons of global functions not attached to objects, oh well.


Also I guess I could get Playsound to work by typecasting as follows:

playsound(TSound(MySound))
where my sound is a ccSound. However, this is pretty much as lame as writing MySound.TheSound, oh well.

Hmm no normally you would not need to assign it, at least if you aren't interested in it.

I guess I should test it. If I make a local Tsound variable X and then call X.Load("Y") if X hasn't been updated by Load, then surely PlaySound(X) or X.Play will fail? If they don't fail because X is set by Load(), then this means that BlitzMax IS able to redefine what Self points at somehow!

Can you view the source code for the modules anywhere? Then I could look at how TSound.Load works.

Does that work?
Type ccSound
  field sound:TSound

  method loadsound(path:string, flag:int)
    sound = ....

  end method

  method playSound()
    playsound(sound ...)
  end method
end type


Perhaps the extend is causing the problem as you add fields and load the sound to a field within your extended sound instead of ccSound variable itself.

yeah that code snippet works. Maybe I'll go with that for now thanks.

OK I tested this:

	Local X:TSound = New TSound
	X.Load("data\SplashSound.wav", True)
	X.Play


and nothing plays whereas

	Local X:TSound = New TSound
	x = X.Load("data\SplashSound.wav", True) 'this line is different
	X.Play


works. I get it now. The method Load is part of the Type but does NOT ACT on an instance, which is why X= is needed at the start of the line. This means that Self is NOT being reassigned. Fair enough.

I know you've sort of sussed it already, but just to clarify.

TSound.Load is a function that returns a TSound type, not a method.

So, you'd use...
local sound:TSound = TSound.Load("data\SplashSound.wav", True)
local chan:TChannel = sound.Play()
...ETC...


yeah thanks, that helps too. Thing is how do you know its a "function" and not a "method" that acts on the instance from the manual?

The definitions for most of the the system types methods and functions can be found in the relevant modules docs (usually at the bottom).

For those that aren't documented, it's a trip to the modules source.

oh yeah just noticed the manual calls Sound.PLay a method (which it is) and Sound.Load a function. Fair enough, I just didn't spot that.