Initialize not getting called for child classes?

I'm running into issues where a child-class's inherited `initialize` method is not being called. I *think* this was working on SDK 1.1.1, but doesn't appear to be working on 1.1.2.

A code example:

class A {
function initialize() {
System.println("here");
}
}

class B extends A {
}

b = new B(); // Does not print "here" like it should

class BFixed extends A {
function initialize() {
A.initialize();
}
}

bFixed = new BFixed(); // Does print "here"
  • This has not changed; you always had to explicitly invoke initialize() on the base class.
  • This has not changed; you always had to explicitly invoke initialize() on the base class.


    Gotcha.
  • I'm still curious about this design decision.

    Was the explicit initialize call for inherited classes an intentional design decision?


    Seems like a sensible default is to inherit the parent's initializer. After all, if you're inheriting it's private attributes, why wouldn't you want those initialized by default for cases where you can't initialize at definition time.
  • I'm in no position to speak for the decisions of the Garmin development staff, but making the derived initialize function implicitly call the base makes things very complicated. What if the two take different parameters? How can the language resolve this automatically?

    Given there is only one initialize method per class, you can't do what most other languages do (call the default if not specified). That said, all languages that I know of require explicit base-class constructor calls if you want anything other than the default.

    In summary, I'm betting that the decision was intentional, and it is to avoid complexity.
  • I'm in no position to speak for the decisions of the Garmin development staff, but making the derived initialize function implicitly call the base makes things very complicated. What if the two take different parameters? How can the language resolve this automatically?


    If the two initializers take different parameters, then the child-class needs to override `initialize` to account for that.

    But it's fairly common, and a good sensible default, to assume that child and parent take the same arguments, so a call to the parents initialize can be done automatically. It they don't match, it's a compile time error that's easy enough for the user to resolve by providing a override for `initialize`.
  • it's fairly common, and a good sensible default, to assume that child and parent take the same arguments, so a call to the parents initialize can be done automatically.

    In which languages is this fairly common? I know that Ruby supports automatically calling the parent constructor if the number of arguments match, but this is the only language that I know of that does it. They added the super keyword and the ability to explicitly call the base class initialize() method via super() to support this. That is the additional complexity that I mentioned in my previous post. Java, C++ and Python either don't inherit constructors at all, or only automatically invoke the default constructor.

    It they don't match, it's a compile time error that's easy enough for the user to resolve by providing a override for `initialize`.

    Unfortunately, I think some of the MonkeyC features conflict with this. If a method takes 3 parameters and you only pass 2, this is not an error. The final parameter is passed through as an unbound reference (null). This feature would make it very difficult to do as you've proposed.

    I'm still interested in seeing what the Garmin guys have to say, but I'm guessing it will be a little while before we get a response.
  • In which languages is this fairly common? I know that Ruby supports automatically calling the parent constructor if the number of arguments match, but this is the only language that I know of that does it. They added the super keyword and the ability to explicitly call the base class initialize() method via super() to support this. That is the additional complexity that I mentioned in my previous post. Java, C++ and Python either don't inherit constructors at all, or only automatically invoke the default constructor.


    Yeah Ruby supports this (if I remember correctly), and in Python, `__init__` it's inherited just like any other method, so if the child class doesn't differ from the parent, there's no need to define `__init__` again in the child.

    If the arguments don't match in Python, then it's just a standard runtime error like any other method call where arguments don't match. It's not treated as anything special.


    Unfortunately, I think some of the MonkeyC features conflict with this. If a method takes 3 parameters and you only pass 2, this is not an error. The final parameter is passed through as an unbound reference (null). This feature would make it very difficult to do as you've proposed.

    I'm still interested in seeing what the Garmin guys have to say, but I'm guessing it will be a little while before we get a response.


    That parameter matching 'feature' of Monkey C isn't all that different from hash-parameters in Ruby and Python's kwargs which both have inherit-initializer semantics.

    You're right, you could potentially end up with argument mismatch errors; these do happen in Python, but on balance, I think inheriting the initializer would be worth it. It'd DRY up some code, where all the child does is call up to the parent and nothing else and, subjectively to me least (others feel free to disagree!) adheres better to the principle of least-surprise.
  • in Python, `__init__` it's inherited just like any other method, so if the child class doesn't differ from the parent, there's no need to define `__init__` again in the child.

    It looks like we've been talking about two different problems; You were talking about the need to explicitly implement initialize() in the derived class. I was talking about the need to need to explicitly invoke the base class initialize() from within the derived class initialize().

    In Python, the base class __init__ is inherited, but it is not invoked automatically. In Ruby I believe it is inherited, and I'm certain that it can be invoked both implicitly and explicitly. In Java, it is not inherited and it is not invoked automatically.

    Travis
  • It looks like we've been talking about two different problems; You were complaining about the need to explicitly implement initialize() in the derived class. I was talking about the need to need to explicitly invoke the base class initialize() from within the derived class initialize().

    In Python, the base class __init__ is inherited, but it is not invoked automatically. In Ruby I believe it is inherited, and I'm certain that it can be invoked both implicitly and explicitly. In Java, it is not inherited and it is not invoked automatically.

    Travis


    Yeah I got the feeling we were talking past each other. I can understand it shouldn't automatically call up to it's parent from within an `initialize`, but if no `initialize` call is provided, the parent's should be sufficient default.