This week's book giveaway is in the Agile and Other Processes forum.
We're giving away four copies of The Little Book of Impediments (e-book only) and have Tom Perry on-line!
See this thread for details.
Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Polymorphism question

 
Claudiu Stroe
Greenhorn
Posts: 29
5
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello everyone!
Here is my question. We have two classes:



and



Why the compiler doesn't let me call the ribbit method.
The method is protected, so it can be accesibile by the child class which is Tadpole and has overidden it ?
So when there are two implementations of the same method, in child and parrent, the method on the object it will run. In this case new Tadpole() not the reference which is Frog f.
 
Stephan van Hulst
Bartender
Pie
Posts: 6503
83
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Because protected members can only be accessed by methods in the same package, and within the body of a subclass, but only if the type of whatever you're accessing the member on is the same as the subclass, or a sub-type thereof.

Frog would be allowed to access Tadpole.ribbit(), but Tadpole is not allowed to access Frog.ribbit() because Frog is not a subclass of Tadpole.
 
Stephan van Hulst
Bartender
Pie
Posts: 6503
83
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here's the related paragraph in the JLS: https://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.6.2

6.6.2. Details on protected Access
    A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.

6.6.2.1. Access to a protected Member
    Let C be the class in which a protected member is declared. Access is permitted only within the body of a subclass S of C.

    In addition, if Id denotes an instance field or instance method, then:
  •     If the access is by a qualified name Q.Id or a method reference expression Q :: Id (§15.13), where Q is an ExpressionName, then the access is permitted if and only if the type of the expression Q is S or a subclass of S.
  •     If the access is by a field access expression E.Id, or a method invocation expression E.Id(...), or a method reference expression E :: Id, where E is a Primary expression (§15.8), then the access is permitted if and only if the type of E is S or a subclass of S.
  •     If the access is by a method reference expression T :: Id, where T is a ReferenceType, then the access is permitted if and only if the type T is S or a subclass of S.
  •  
    Claudiu Stroe
    Greenhorn
    Posts: 29
    5
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I still don't get it. Now I'm more confused trying to add :



    As i understand till now methods from the reference (Frog) is restricted as been set to protected, even if the reference points to an object which is a subclass.

     
    Ramya Subraamanian
    Ranch Hand
    Posts: 178
    17
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator


    Here the Object is a Tadpole, but it is stored in a Frog reference. The protected modifier specifies that the member can only be accessed within its own package and in addition by a subclass of its class in another package.They are not in the same package and Frog is not a subclass of Tadpole. Although f.ribbit() calls the overridden subclass method at runtime. It has access to only the superclass ribbit at compile time..Since it is not accessible, it gives a compiler error.


    you cannot access it with f1 as well like in line 2. it throws a compiler error.

    But it can be accessed with the subclass reference like in line 1 . Because Tadpole is a subclass of Frog.
    and accessed without a variable , because Tadpole inherits the superclass methods like in line 3.
     
    Stephan van Hulst
    Bartender
    Pie
    Posts: 6503
    83
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    It doesn't matter what the value of f at runtime is. The formal type of f is Frog. You're trying to access a protected member on it. You can't do this, because Frog is not a Tadpole or a sub-type of Tadpole.
     
    Claudiu Stroe
    Greenhorn
    Posts: 29
    5
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thanks a lot Ramya and Stephan!
    After practicing and done some experiments I got it!
    In the beginning I missunderstood the concept of protected.
     
    Ramya Subraamanian
    Ranch Hand
    Posts: 178
    17
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    refer to pages 176-179 in the Sybex OCA study guide. It has a very similar example.

    Also there's an typo in page 179, Where in the para after the code snippet..it must "Bird is not a subclass of Goose".
    http://www.selikoff.net/java-oca-8-programmer-i-study-guide/

    And Roel's illustrative code snippets in reply to this errata is worth reading
    http://www.coderanch.com/t/661025/ocajp/certification/potential-Errata-Java-OCA-Programmer
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Claudiu Stroe wrote:After practicing and done some experiments I got it!
    In the beginning I missunderstood the concept of protected.

    Let's put your knowledge to the test and see if you actually understand it

    What happens if we move the main method from the Tadpole class to the Frog class?

    And what happens if we add another subclass of Tadpole which also overrides the ribbit method

    And I agree with Ramya: this topic is definitely worth reading! It has some code examples about birds, gooses, and wild gooses, very similar with the frogs, tadpoles, and big tadpoles

    Hope it helps!
    Kind regards,
    Roel
     
    Claudiu Stroe
    Greenhorn
    Posts: 29
    5
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thanks Roel for this challenge!

    In first example where we have Frog class, with main method and Tadpole extedns Frog


    For line 1 - Tadpole's ribbit() method is protected so it si not accesibile here. It is accesible only in the subclass , or in the same package, but main method is now in SuperClass
    for line 2 - Tadpole's ribbit() method must be used here, but since is not accesilbe here we have again a compile error
    }
     
    Claudiu Stroe
    Greenhorn
    Posts: 29
    5
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    In the second example :



    Here if we use
    Tadpole bt = BigTadpole();
    instead of
    BigTadpole bt = new BigTadpole();
    bt.ribbit(); will compile and the output would be "BigTadpole ribbit".
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Claudiu Stroe wrote:Thanks Roel for this challenge!

    I'm really famous for the additional (and free of charge) pop quiz (mock) questions

    Claudiu Stroe wrote:For line 1 - Tadpole's ribbit() method is protected so it si not accesibile here. It is accesible only in the subclass , or in the same package, but main method is now in SuperClass

    You are spot-on! This line will give a compiler error, because the protected ribbit method of the Tadpole class will not be accessible. Because the method is invoked from a different package, the method is not visible and therefore can't be invoked using the dot operator (you can invoke the method from within a subclass using inheritance). Like in this code snippetAnd then in the main method of the Frog class you can add

    Claudiu Stroe wrote:for line 2 - Tadpole's ribbit() method must be used here, but since is not accesilbe here we have again a compile error

    That's incorrect! You are probable so focused on the protected keyword and the consequences, that you are missing the really obvious The main method is defined in the Frog class and you have a Frog reference variable, so you can access any method (even private ones) using the dot reference. So you can invoke the ribbit method without any problem. For this statement the Tadpole class is completely irrelevant and doesn't matter at all! Do not forget that the compiler does not execute any code at all, so the compiler does not know (and does not care) that reference variable f is referring to a Tadpole object. Invoking a private method from another method defined in the same class (even the main method) is allowed, as this code snippet illustrates

    Hope it helps!
    Kind regards,
    Roel
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Claudiu Stroe wrote:bt.ribbit(); // BigTadpole's ribbit() method is not accesible here

    Exactly! For exactly the same reason as t.ribbit(); (line1) in the first code snippet.

    Claudiu Stroe wrote:t.ribbit(); // it compiles here and outputs "Tadpole ribbit"

    You are correct! And here the reason is exactly the same as f.ribbit(); (line2) in the first code snippet.

    Claudiu Stroe wrote:f.ribbit(); // it compliles to, Tadpole's ribbit() method is outputed here,

    Here you are incorrect! That statement will produces a compiler error. Let's see if you can explain why...

    Claudiu Stroe wrote:Here if we use
    Tadpole bt = BigTadpole();
    instead of
    BigTadpole bt = new BigTadpole();
    bt.ribbit(); will compile and the output would be "BigTadpole ribbit".

    That's indeed spot-on! bt.ribbit(); will definitely compile, but Tadpole bt = BigTadpole(); will fail to compile because the new operator is missing

    Hope it helps!
    Kind regards,
    Roel
     
    Claudiu Stroe
    Greenhorn
    Posts: 29
    5
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Ok ...
    When I thought that I managed to understand this subject, you again saved me.
    I analyzed the code again, and again, and this rules comes up in my mind to summerieze this subject

    1. If the main method is in the reference class, the compiler knows that all methods in that class are available.( All access modifiers are available in the same class)
    2. If the reference class's available methods are override in the object class,the overidden version will be outputed at runtime. (Only the reference class's variables are available)
    3. If the reference class is different from the class that has the main method, you can access those methods only if the access modifier permit it :
    - private is never accessed here;
    - package-private is availble if the class that has the main method is in the same package;
    - protected - is tha same as default modifer + gives access to subclasses ( only if the reference is the class that has the main() and equals to a subclass) ;
    - public - accesible anywhere;

    Please correct me if I'm wrong and thanks again

    P.S: sorry for grammer or spelling mistakes
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Claudiu Stroe wrote:1. If the main method is in the reference class, the compiler knows that all methods in that class are available.( All access modifiers are available in the same class)

    This is of course not limited to the main method, but applies to all methods (both static/class and instance) in a class. Any method defined in a class can access every method defined in that class, even using the dot operator. Of course the rules about static context and non-static context are still valid (e.g. from a static method you can't directly invoke an instance method). An illustrative code snippet

    Claudiu Stroe wrote:2. If the reference class's available methods are override in the object class,the overidden version will be outputed at runtime. (Only the reference class's variables are available)

    True! That's a very comprehensive summary of these two very simple (and hopefully easy to remember) but very, very, very important rules:
  • Which instance variables you can access is determined at compile time based on the reference variable type.
  • Which instance methods you can call/invoke is determined at compile time based on the reference variable type. Which instance method is actually executed is decided at runtime based on the type of the actual object (= polymorphism).


  • Claudiu Stroe wrote:3. If the reference class is different from the class that has the main method, you can access those methods only if the access modifier permit it :
    - private is never accessed here;
    - package-private is availble if the class that has the main method is in the same package;
    - protected - is tha same as default modifer + gives access to subclasses ( only if the reference is the class that has the main() and equals to a subclass) ;
    - public - accesible anywhere;

    You are correct on three of the four access levels, but I have my doubts about the protected access modifier. I don't think you can easily state this in just one sentence, because there are a few little intricacies (as illustrated in this topic and this one). And again, it's not only restricted to the main method, but applies to all methods (both static/class and instance) in a class.

    Hope it helps!
    Kind regards,
    Roel
     
    • Post Reply
    • Bookmark Topic Watch Topic
    • New Topic