re: constructors with parameters.
Is there a reason why this hasn't been implemented in BMax?
Mainly because I wanted to keep things simple!
When you construct an object, it is actually constructed multiple times - first the superclass is constructed, then this class, then subclasses etc.
This gets a little messy when parameters are involved as you then need a mechanism to pass parameters up to the superclass at construction time, eg:
Type Base
Method New( x )
End Method
End Base
Type TDerived
Method New( x,y,z )
End Method
End Type
Derived's New has to somehow pass 'x' up to Base's New at construction time. In Java, Derived's New would do something like 'Super.New( x )' before executing super's New.
Not impossible, but just something I decided to leave out in order to keep things simple. Actually, thinking about it now I could have gone for 'non-overloaded constructors with parameters' - ie: if Base.New has one parameter, so must Derived.New. But at the time I was playing with the idea of 'Type objects'...
Similarly, I left out overloading to keep things simple. Most languages with overloading end up with pretty complex rules for selecting the correct function/method at compile time. eg:
Function Func( x:Int )
End Function
Function Func( y:Float )
End Function
Local t:Double=10
Func t
Which Func should be called? Certainly, you can start creating rules such as 'the float one because it's type is nearer' - which logically maps to the current rules - or 'neither because there are multiple versions but no exact match', but once you throw in some inheritance things can get a bit messy.
Another dodgy aspect of overloading is it's typically a 'static' thing that is determined at compile time. This can lead to a few surprises such as...
Function Func( t:Base )
End Function
Funciton Func( t:Derived )
End Function
Local t:Base=New Derived
Func t 'only calls the Base version - careful!
In my time as a C++ coder, I ended up avoiding overloading as much as possible and instead named functions more sensibly - eg: FuncInt() and FuncFloat(). That said, I have since encountered better overloading systems and would probably think twice about leaving it out given the chance again.
As far as reflection is concerned, this is the ability to dynamically query an object to determine the types of it's members - it's fields, consts, methods, globals and functions.
However, for this to be really useful you need some mechanism to actually use these - which is hard. Objective C does this beautifully, but at the price of having to 'interpret' all method calls. Still, it's 'fast enough' for a huge number of situations.
I don't consider reflection to be a cure-all for magic object serialization. Objects will often contain 'extra data' like caches, or other objects that are trickier to reconstruct - for example, how would you serialize a TStream? How was the stream opened? Ditto a TPixmap - where did it come from? A file? A custom routine? Just dumping the contents of the TPixmap is probably not ideal...
Certainly, in some cases a 'blind' serializer would do the trick, but you'd have to be pretty careful with what you threw at it. You could argue that this is better than 'no reflection', but in my opinion the ability to query/call methods on objects is far more interesting and I would have considered reflection broken without it!
Dynamic class loading is really just loading types and the associated code as you need them at runtime - sort of a subset of DLL loading. It's mainly useful for plugins etc - or, god forbid, remote code - but really requires a specialized runtime system - ie: it'd be hard to wedge into Max's compile/link system the way it is. Most languages that support dynamic class loading are either interpreted or use a VM.
I have consider dynamic module loading, but it would involve some overhead - you'd have to basically add a level of redirection for all globals, function, types in a module. Perhaps not too bad...?