Extremely Serious Bug in Monkey C!!!

Let's take such class:

class A
{
  hidden var myLocal = "Var from A";

  function do_localModyfication()
  {
    myLocal += " + some modyfication";
  }
}


Then write next class:

class B extends A
{
  // completely by accident 
  hidden var myLocal = "Var from B";

  function test()
  {
    do_localModyfication();
    System.println(myLocal);
  }
}


How do you think what you'll see in the log after B.test() call?

You will see: "Var from B + some modyfication" :confused::p !

And at the end imagine that you are using class for which you have no sources, like View or WatchFace. Please Garmin, tell me if I should pray that my var names are different than yours? Otherwise, your class and mine will explode!

This of course is a BIG BUG and we should only see: "Var from B"

I wonder why Garmin didn't decided to chose eg. C# which is free. Writing in C# if you build your program without warnings you can assume that it will work as intended. In my opinion Monkey C (Java like) it's probably not the best choice and may leads to unstable software.

Peter

  • Your test doesn't make a lot of sense without some other information.

    class A
    {
    hidden var myLocal = "Var from A";

    function do_localModyfication()
    {
    myLocal += " + some modyfication";
    }
    }

    class B extends A
    {
    // completely by accident
    hidden var myLocal = "Var from B";

    function test()
    {
    do_localModyfication();
    System.println(myLocal);
    }
    }


    Taking that code if I used class A by itself and called <instance>.test(), I would expect a symbol not found error. The A class would have no knowledge of B class. If I instantiated with class B and called <instance>.test(), I would expect the result you got. The hidden variable is the same as private scoping in other languages and wouldn't have the ability to see the variable.
  • Taking that code if I used class A by itself and called <instance>.test(), I would expect a symbol not found error.


    Of course it does not make sense. Your test code should look like this:
    function main()
    {
    var objB = new B();
    B.test();
    }


    I corrected A.test() to B.test();

    Peter
  • Thanks for pointing this out. :)

    Monkey C behaves more like Python and Ruby than Java or C# in this case, so this is essentially by design. The result you're seeing isn't absolutely incorrect--it just depends on the language. That said, we believe that this requires some consideration. You have some valid points, and since we have plans to grow the Monkey C language down the road, it makes sense for us to take this behavior into account.

    So far, this hasn't caused anyone any trouble that we are aware of, but please let us know if this becomes a common problem!
  • Thank you Brandon for your replay.

    But perhaps this is the opinion of many of us that what is hidden and my private can not be changed by external objects. In documentation we read only about function inheritance. There is nothing about variable (property like but without getter and setter) inheritance. I can agree that public fields (variables) could be inherited but without getters and setters it only leads to errors.

    For me it is like a bomb that can explode at the least expected moment. I would feel much better if you promised that in CIQ 1.2.3 hidden will means: no one is able even to read it except owner :).

    Thank you,
    Peter
  • I would feel much better if you promised that in CIQ 1.2.3 hidden will means: no one is able even to read it except owner :).


    It is the expected behavior, and is discussed in the the Programmer's Guide...

    Data Hiding
    Classes have two levels of access—public and hidden. Public is the default. Hidden is the same as “protected”; it says that a variable or function is only accessible to a class or its subclasses...


    Travis
  • Yes Travis, according to the documentation subclass B can access 'myLocal' from class A using syntax A.myLocal but superclass A shouldn't never has access to 'B.myLocal' even when myLocal in B would not be hidden.

    Peter
  • Former Member
    Former Member over 9 years ago
    Peter, FWIW, I completely agree with you. The problem seems to stem from a confluence of two things: the language has a single completely flat 'symbol' space (a symbol with the same name is the same symbol through out the execution instance of the vm, no matter where the symbol occurs), and that the objects seem to be implemented with a simple single-level dictionary for the object instance variables. This really should be fixed asap if Garmin cares to ensure both developer and user experience.
  • I think that solution acceptable to all could be:

    1. Variable inheritance MUST be completely removed.
    2. The keyword hidden remains as it is.
    3. New keyword private will isolate functions and variables from outside world.

    Peter
  • This is the behavior in python...

    <Fri 01/08/2016 11:10:43.32>
    C:\test>type t.py

    class A(object):

    def __init__(self):
    self.myLocal = "Var from A"

    def do_localModyfication(self):
    self.myLocal += " + some modyfication"


    class B(A):

    def __init__(self):
    super(B, self).__init__()
    self.myLocal = "Var from B"

    def test(self):
    self.do_localModyfication()
    print self.myLocal


    def main():
    b = B()
    b.test();

    if __name__ == "__main__":
    main()


    <Fri 01/08/2016 11:14:27.44>
    C:\test>python t.py
    Var from B + some modyfication


    <Fri 01/08/2016 11:14:31.21>
    C:\test>


    Are you also suggesting that python suffers from this same problem?
  • I've looked at this issue a few times, and I must be missing something. You are complaining about how hidden doesn't prevent access to the variable in the base class, but as far as I can tell, _nothing_ in this code accesses A.myLocal and the whether or not myLocal is hidden or not does not have any impact on the behavior of the program. So lets rewind a bit. What _exactly_ are the problems that you are so concerned about?

    1. Variable inheritance MUST be completely removed.

    I'm afraid I don't understand what problem you are trying to solve by doing this. I see that this would change the definition of extends to be more like Java's implements where it just allows the base to describe the interface for a derived type, but you don't need that in MonkeyC; it is a duck-typed language so interfaces are irrelevant.

    3. New keyword private will isolate functions and variables from outside world.

    Again, what problem (exactly) are you trying to avoid? You don't want derived classes to have access to the base class state? Is that it?