Questions related to Java polymorphism - java

public class Test{
public static void main(String[] args){
new Person().printPerson();
new Student().printPerson();
}
}
class Student extends Person{
private String getInfo(){
return"Student";
}
}
class Person{
private String getInfo(){
return "Person";
}
public void printPerson(){
System.out.println(getInfo());
}
}
I have some questions related to Student().printPerson() in the second line of the main function.
What I know is that: Java will first try to find the printPerson() in Student class. Since it couldn't find one, it will go to find the printPerson() in the superclass of Student which is Person. Now it executes the Person's printPerson() and here are my questions:
The printPerson() invokes another method getInfo(), so which getInfo will Java choose? Could you please explain with details?
Please explain how the modifiers of the getInfo() affect the output.
For your reference, If I remembered correctly. If the modifiers of both getInfo() are public, the output will be: Person Student If they are both private, the output will be Person Person

I’m on my mobile, so forgive me for grammar and typos.
Also disclaimer, I’m not heavy with java implementation so I am giving a generic explanation and I may have a few things incorrect with how java implements.
What happens is because of access level modifiers and restricting scope.
For your person class,
You have your two methods, public print and private getInfo.
You person class can see both the methods.
Your student class you have one method, private getInfo, and you extend the person class.
Because getInfo is private, it is only know to that class and nothing else. Because of this Java will not override the super (person) getInfo with the Student’s getInfo.
Because the method is not be overridden when Student.Print is being called, student.super.print is resolving to the student.super.getInfo method instead of student.getInfo.

Related

Static/dynamic binding in Java

I do have class Person, class Student and Student extends Person. As far as I understood, it goes the following with static binding:
class Person {
talk(Person p) {
print("Hi by person.");
}
}
class Student extends Person {
talk(Student s) {
print("Hi by stud.");
}
}
Now if I instantiate and call method:
Person x = new Student();
talk(x);
// output: "Hi by person." because of static binding, am I right?
My Question:
What if only class Student has a method talk(Student s). Now I call talk(x). Since I usually should get talk() method from class Person, what happens when there is no such method?
EDIT: I tried to run it and it gives me an Compile Error. Ok, but why does this happen? I learned that the compiler will first go to the subclass and search for the method and if it's there, then it gets executed?
Don't exist dynamic binding for overloaded methods ...
and Student is a Person so method talk from Person invoked

class members that are inheritable

I was studying for my OCA cert. and stumbled on a sample question.
it gives you a code and asks you to figure out which option is correct. The code looks like:
class Employee {
private String name;
string address;
protected String phonenumber;
public float experience;
}
class Programmer extends Employee {
programmer (String val){
name = val;
}
String getName() {
return name;
}
}
class Office{
public static void main (String args[]){
new Programmer ("Harry").getName();
}
}
Now the answer for this question was "compilation error". I understand this is correct because you can't access the String 'name' since it is private.
But among the option there was one that said: "The derived class Programmer can't access variables of its base class in its constructors."
Now, I thought this was basically saying that constructor 'Programmer' can't access variable 'name' from its base class 'Employee' (because the variable is public). Which lead me to believe this was also a correct statement. However, the answer page from the book stated compilation error option was the only correct statement.
I was hoping if anyone could explain why that statement is wrong.
"The derived class Programmer can't access variables of its base class
in its constructors."
Well, a class can access variables, independent of it being in the constructor, in a method, or in the declaration part. That just doesn't matter.

Using Java reflection to modify nesting class's fields from inner class

I'm experiencing odd behavior while debugging my Java reflection homework in Eclipse.
I have 2 classes defined:
public class OuterClass{
protected Person person;
public void aPerson(Integer age) {
person = new Person(age);
}
}
public class OuterDerivedClass extends OuterClass {
public class InnerClass extends OuterClass {
public void aPerson(Integer age) {
person = new Person(age);
}
}
}
At some point in my program, I instantiated an InnerClass instance like so (using reflection as my program is supposed to work on any class. Nested classes could be either static/non-static and public/private/protected):
Class<?> outer_class = outer_instance.getClass();
Constructor<?> ctor = inner_class.getDeclaredConstructor(outer_class);
Object inner_instance = ctor.newInstance(outer_instance);
Later on I invoked the OuterDerivedClass$InnerClass.aPerson method:
method.invoke(inner_instance, parameter);
For now, it seemed like all went OK: The inner_instance was created successfully, the correct aPerson method (the one in InnerClass) was invoked. BUT, later on my program, as I tried to access the person field from outer_instance, I figured out it was still NULL (though it was created in aPerson method).
While debugging in Eclipse, I found out this:
(PersonStoryDerivedTest == OuterDerivedClass in my question).
The id of this$0 is the same as the one I sent to the constructor (outer_instance). I couldn't figure out what is the second person field (the one that apparently was created by invoking aPerson). Isn't this field supposed to exist only in the nesting class? My intention was that the invocation of OuterDerivedClass$InnerClass.aPerson would change the person field in outer_instance (I thought this is the reason why it was sent to the Constructor in the first place).
Can someone please clarify these issues? Thanks!
I couldn't figure out what is the second person field
Well, since
public class InnerClass extends OuterClass {
// ^^^^^^^^^^^^^^^^^^
your InnerClass also inherits its own person field which is set by
public void aPerson(Integer age) {
person = new Person(age);
}
because person refers to this.person and this inside this method represents instance of class where method was implemented (in InnerClass).
If you want your method to initialize OuterClass#person field you need to refer to it via OuterDerivedClass.this.person, but this will leave uninitialized person field of InnerClass.
Other (simpler) option is not extending OuterClass from InnerClass:
public class InnerClass{

Java: A public method inherited from superclass invokes a private method.

public class Test {
public static void main(String args[]){
Student s = new Student();
s.printPerson();
}
}
class Person{
private String getInfo(){
return "Person";
}
public void printPerson(){
System.out.println(getInfo());
}
}
class Student extends Person{
private String getInfo(){
return "Student";
}
}
The output is Person. I am confused with this result. In the main method, the reference type is Student. So when executing s.printPerson(), it should executes the method of Student. The key point is, in the public method inherited from superclass, which private method is invoked? And why?
I thought in s.printPerson(), it invokes getInfo() of Student. But it turns out not. The IDE tells me
private String getInfo(){
return "Student";
}
is never used.
Can anyone help me with this please?
In Java, private methods are not inherited.
A subclass does not inherit the private members of its parent class. However, if the superclass has public or protected methods for accessing its private fields, these can also be used by the subclass.
You cannot override getInfo by creating another getInfo method because it's not inherited. That's why your IDE gave you the "never used" warning, because nothing in Student uses it. The getInfo from Person is called, because it is available to Person's printPerson method, so Person is printed.
To override a method, it must not be private. You can make getInfo package-private (no access modifier), protected, or public. Then Student will be able to override it.
You use the private modifier. This modifier means that the method is only visible from within the class itself, not other classes, not even its sub- and superclasses. So when you call getInfo() from class Person, the only method visible is the method defined in the Person class. Effectively this means that private methods are not inherited in Java.
Try to change the private modifier to protected. Then the subclasses can see the method from the superclass, and so they can overide the method.

Why derived class overriding method should not be more restrictive than base class in java?

Why derived class overriding method should not be more restrictive than base class in java.Why compiler throws error?can you please anyone explain reason for that?
The point is that a caller who only knows about your superclass should still be able to use any instance of the subclass that it's given. Consider this situation:
public class Super
{
public void print()
{
System.out.println("Hello!");
}
}
public class Sub extends Super
{
#Override
void print() // Invalid
{
System.out.println("Package access");
}
}
Now from a different package, imagine we had:
public void printSuper(Super x)
{
x.print();
}
and we called that with:
printSuper(new Sub());
What would you expect that to do? You're overriding the method, so it should print "package access" - but then that means you're calling a package access method from a different package...
Basically, this is just one example of the Liskov Substitution Principle in action. You should be able to treat any instance of a subclass as an instance of the superclass, and it's hard to see how that fits in with making things more restrictive in a subclass.
You can not make access modifier more restrictive, because that would violate the basic rule of inheritance that a subclass instance should be replacable in place of a superclass instance.
For e.g
Suppose that Person class has getName public method which is being used by many classes(including non-sub classes).But somebody just added Employee as subclass of Person and getName in
Employee is protected which should be accessed only by sub-classes then the previous code would start breaking and Employee would not be replacable to Person object.
Hence java has decided to impose this restrcition.
The overriding message should not be more restrictive then the overridden method because an instance of the child class should always be able to be used in a place where an instance of the superclass is expected. But if a method is more restrictive, it may not be accessible if the call is coming from another class or package. For example, imagine this:
//File Number 1
public class Human {
public int age = 21;
public int getAge() {
System.out.println("getAge() method in Human");
return age;
}
}
//File Number 2
public class Teacher extends Human {
public int getAge() {
System.out.println("getAge() method in Teacher");
return age;
}
}
//File Number 3
public class Characteristics {
public static void showAgeOfObject(Human human) {
human.getAge();
}
public static void main(String[] args) {
Human human = new Human();
Teacher teacher = new Teacher();
showAgeOfObject(human);
showAgeOfObject(teacher);
}
}
Now if both getAge() methods are public, this will be displayed
getAge() method in Human
getAge() method in Teacher
But if getAge() in Teacher was private, this would throw an error because we are in a different class which therefore cannot access the method.
Consider below example
class Mammal {
public Mammal readAndGet() throws IOException {//read file and return Mammal`s object}
}
class Human extends Mammal {
#Override
public Human readAndGet() throws FileNotFoundException {//read file and return Human object}
}
And if we execute below code
Mammal mammal = new Human();
Mammal obj = mammal.readAndGet();
And we know that for compiler mammal.readAndGet() is getting called from the object of class Mammal but at, runtime JVM will resolve mammal.readAndGet() method call to a call from class Human because mammal is holding new Human().
Method readAndGet is defined public in Mammal and in order to make it less restrictive in class Human we will need to either remove the access specifier (making it default) or make it protected or private.
Now suppose
If we define readAndGet as default or protected in Human but Human is defined in another package
If we define readAndGet as private in Human
We know JVM will resolve readAndGet method call at runtime but the compiler is unaware of that and in both cases, the code will compile successfully because for compiler readAndGet is getting called from class Mammal.
But in both cases at runtime JVM will not be able to access readAndGet from Human because it will be restricted due to restrictive access of readAndGet in Human class.
And also we can not be sure of who will be extending our class in future and in what package he will be doing that and if that guy makes the overriding method less restrictive JVM might not be able to call the method and code will break at runtime.
So to avoid this uncertainty, assigning restrictive access to the overriding method in the child class is not allowed at all.
There are other rules as well which we need to follow while overriding the methods and you can read more on Why We Should Follow Method Overriding Rules to know the reasons.

Categories

Resources