Static/dynamic binding in Java - 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

Related

Questions related to Java polymorphism

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.

Cannot call some methods in interface after instantiating the objects in Java

I have this code sample as you can see. But when I try to compile, it gives an error saying in id.input the object reference variable id cannot be found. Can someone please help me?
interface IDisplay{
void print();
void printDetails();
}
interface IInput{
void input();
}
class Book implements IDisplay,IInput{
int bookID;
String title,publisher;
public void print(){
}
public void printDetails(){
}
public void input(){
}
}
class Student implements IDisplay,IInput{
int studentID;
public void print(){
}
public void printDetails(){
}
public void input(){
}
}
class A{
public static void main(String[] args) {
IDisplay id=new Student();
id.print();
id.printDetails();
id.input();
}
}
A Student instance will be able to call all methods of IInput and IDisplay method but, it depends how you manipulate it
Because you stored if in IDisplay, the methods of IInput are not visible
Solution :
Cast in IInput
IDisplay id = new Student();
id.print();
id.printDetails();
((IInput) id).input(); // or ((Student) id).input();
Store in Student type
Student id = new Student();
id.print();
id.printDetails();
id.input();
At compile stage, the compiler only knows that id's reference type is IDisplay, it does not know id's runtime type is Student.
Since IDisplay does not have method input, you got compile error. To make it compile, you can cast it explictly:
((Student)id).input();
Interface IDisplay has only two methods print and printDetails and the method input is in the interface IInput.
In your code, the object id is of type IDisplay (even though it holds a reference to a Student object) and hence you can only call the methods on the interface IDisplay.
You either have to cast the id object to either Student or IInput to call the input method
((Student)id).input();
((IInput)id).input();
Or
have id as type Student.
However, it could be argued that the former violates some OO principles as a IDisplay has to only be an IDisplay and an IInput has to be only an IInput
That is because id is of type IDisplay and not of type Student.
IDisplay does not have method input()
If you want to invoke a method from Student, you can cast it as Student:
((Student)id).input();
or cast as IInput:
((IInput)id).input();
or instantiate as Student:
Student s = new Student();
s.input();
when you instantiate an object (id) type of IDisplay, cause JVM casts it to an object, IDisplay of type.
so it has been instantiated only with implemented methods of interface IDisplay despite you used the constructor of class Student which implements IDisplay and IInput.
if you intend object id to access to implemented methods of the both interfaces IDisplay and IInput, you should modify your code to:
class A{
public static void main(String[] args) {
Student id = new Student();
id.print();
id.printDetails();
id.input();
}
}

Im having trouble understand this boolean logic. Can someone please explain it please

The following is what I am having trouble understanding:
interface CheckPerson {
boolean test(Person p);
public static void printPersons(
List<Person> roster, CheckPerson tester) {
for (Person p : roster) {
if (tester.test(p)) {
p.printPerson();
}
}
}
I understand that this method is saying if true print person... however what I do not get is how does
boolean test(Person p);
work and what is it saying.
Perhaps if I understand this I can understand
if (tester.test(p)) {
p.printPerson();
Thank you for your help... I'm still learning.
I think what you don't understand is why you can still call test when the method body for test is missing.
First you need to know that the test method is in something called an interface. Methods in interfaces generally don't have implementations (method bodies). Also you can't initialize an interface directly by calling its constructor. You can only create an instance of a class that implements the interface.
A class can implement an interface by saying:
public class MyClass implements CheckPerson {
}
And the class needs to provide the necessary methods (in this case, test).
public boolean test (Person p) {
//implementation goes here...
}
Now let's look at your printPersons method. It takes a CheckPerson object and a list of persons. Now here comes the interesting part, when you want to call this method, you can't simply just:
List<Person> list = new ArrayList<> ();
list.add(somePersonObject);
CheckPerson.printPersons(list, new CheckPerson());
*****************
this part is wrong!
As I said before, an interface cannot be instantiated directly by calling its constructor, you need to instantiate a class that implements it and pass that to the method. You see, this is why tester.test works. Because test will always be a class that implements the interface and thus test will always have a body! Let's see this in action:
Let's create a class called AdultTest:
public class AdultTest implements CheckPerson {
public boolean test (Person p) {
return p.getAge() > 18;
}
}
Note: I don't know what your Person class is like, so I made getAge() up. Don't try to use it in your code if your person class doesn't have it.
Now we can call printPersons without error:
CheckPerson.printPersons(list, new AdultTest());
And then it will print all the people whose age is greater than 18.
"But why should I create an interface to achieve this? Couldn't I just create a method that accepts a AdultTest object to test it?" you asked. That's a very good question!
The benefits of using interfaces is that you can easily expand its functionality. For example, I can create another class that tests if the person is a female:
public class FemaleTest implements CheckPerson {
public boolean test (Person p) {
return p.getGender().equals("Female");
}
}
Again, getGender is made up.
Now you can just pass new FemaleTest() to the printPersons method!
If you don't create a new class for this, you need to create a new method that accepts a FemaleTest object, which is a lot of repeated code. Not good!
if (tester.test(p))
This peace of code means:
You have an instance of CheckPerson named tester, and the class which implemented the Checkperson of which tester is an instance must have the logic to define test method which accepts Person object as parameter.
Now the return type of your test() method is a boolean, so in your if condition(if (tester.test(p))), based on the boolean value returned true or false it will either go into condition to print or it will not go inside condition if boolean value is false.
Note: if condition accepts boolean values i.e. true or false, so as your test() method returns a boolean value it is a valid expression.

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 inheritance and object casting

I am quite new to programming, i have a question please help me. ( this question is java question but i can't remember the syntax but what i write here is mostly it.)
A class Person speaks "i am a person"
A class Student speaks "i am a student"
Student extends from Person
Person p = new Student
then what is p speaking then?
p is just variable, it doesn't change the type of the Object that's in it.
You can think of a cup: You can put any fluid in it, but the cup won't change the type fluid.
abstract class Fluid{
public String getTemp(){
return "unknown";
}
}
class Coffee extends Fluid{
public String getTemp(){
return "hot";
}
}
class Cola extends Fluid{
public String getTemp(){
return "ice-cold"
}
}
Fluid cup = new Coffee();
System.out.println(cup.getTemp()); //It's coffe in there, so it's hot!
p is both a Student and a Person but if you call a method (like whoAreYou()), Java will first try to find it in Student and then in Person.
"I am a student"?
This is called Dynamic Binding
I think I know what you mean...
p would say he is a student, because you will override the method where the person speaks. In Java, it should look like this:
class Person
{
public void speak()
{
System.out.println("I'm a person!");
}
}
class Student extends Person
{
#Override
public void speak()
{
System.out.println("I'm a student");
}
}
"i am a student"
This is Java's polymorphism in action. The method speaks() is defined in base class Person and is overridden in the derived class Student.
In Java a base class reference can refer to a derived class object, and when a overridden method is call on such a reference, the type of the object to which the reference refers to decides the version of the method to be executed.
Even though your reference to p is declared as a Person, p is actually an instance of Student. Therefore p will "speak" whatever a student speaks.
It is legal to have refer to a Student instance as a "Person" since "Student extends from Person".
P will say student. Because Student object is casted into Person object.
Above question completely belonging to inheritance mechanism same property used by different entities.
class Person {
String identity;
Person() {
this.identity = "Person";
System.out.println("A class " + this.getClass().getName()
+ " speaks i am a " + identity);
}
}
public class Student extends Person {
public Student() {
this.identity = "Student";
System.out.println("A class " + this.getClass().getName()
+ " speaks i am a " + identity);
}
public static void main(String[] args) {
Person p = new Student();
}
}
I would guess "i am a student". This is basic polymorphism.
If the method is not static then the Student's method will be called as others mentioned. Just be careful that if the method speak is static, then the Person's method will be called. This is called hiding.
Here it is showing the concept of Polymorphism like Super class can hold the reference of child class along with that it is also showing the concept of Inheritance like Student is a Person means class Student extends Person. So here Person is a Super class and Student is a child class. As per the polymorphism Person Class (Super Class) can hold the reference of Student class (Sub-Class).
P will Speak : I am student.
But it will only have common behavior of both class. any behavior which student has but not in Person, P will not be able to access that behavior.
Person "P" is a reference here which is initialized with object of student. So when the execution of program will start, at runtime Student's class function will be called.
Here P is the Parent class Object that is holding the child class object. this is because here parent and child relationship(through inheritance ) exists because you are extending the Parent class into the Student class. Thus Parent class Object can hold the Objects of all its children class. Now P can access all the properties of its child class.
In Java when Student extends from Person you can decide what kind of behavior Student invokes from person , You can restrict student to say if it is person, You can implement it as an static then static methods are not overridden. they just shadow. If Intentionally you want instance method then you implement its specific behavior.
There is dynamic method dispatch/dynamic binding.
Person p = new Student();
p is a reference variable that type of Person which called to Student object.Student is child class and Person is parent class which extended.Two classes has methods that static or not.
Here p will speak I am a student. This is an example of dynamic binding.
This is a example of single inheritance in java.In this example,"Person" is a base class where as "Student" is a derived class.Unless anything is specified,
Person p=new Student();
object p(it seems like object of Person) will access the properties of Student class which has overriden the properties of its own base class Person.

Categories

Resources