I can't invoke the method defined in the subclass - java

I have 2 classes:
public class Animal {
protected String name;
int age;
public Animal(String name, int age) {
// TODO Auto-generated constructor stub
this.name = name;
this.age = age;
}
public static void eating() {
System.out.println("eating");
}
}
public class Human extends Animal{
public Human(String name, int age) {
// TODO Auto-generated constructor stub
super(name, age);
}
public static void talking() {
System.out.println("Talk");
}
}
main program:
public class program {
public static void main (String [] args) {
Animal hum = new Human("bob", 1);
System.out.println(hum);
//hum.talking();
}
}
The output of the main program is wk05.Human#7f690630. So why I can't do "hum.talking" in the main program? My understanding of inheritance is that the subclass can invoke the methods defined in the parent class as well as the method defined in the subclass.

Here in your program Animal hum = new Human("bob", 1); means hum reference to Animal super class which does not have definition of talking() and object is Human.
At compile time reference is considered rather than the object. Object is used at runtime. So if you want to call talking() you would need to:
1) Create reference to Human class
Here the reference is also to Human class so it has the definition of talking() method at compile time.
Human hum = new Human("bob", 1);
hum.talking();
2) Cast object to Human (only for understanding the type-casting)
When we cast the object we explicitly tell the compiler to refer the defined object. So it can refer that.
Animal hum = new Human("bob", 1);
((Human) hum).talking();
Reason behind is that let's say you have one more class SuperHuman which also extends Animal class and that class doesn't have talking() method then how the compiler would be knowing that reference hum will be referring Human or SuperHuman?
And let's say during initialization you have we have done like Animal hum = new Human("bob", 1); and later in code the hum is updated to hum = SuperHuman("sup", 10);. That's the reason compile time reference is referred and Object is referred at runtime.

The error is a compile error; the compiler doesn’t care what the object type actually is (or could be), it only cares about what it’s declared as.
Also, I’m almost certain your methods should not be static.
If you were to do something like what you’re exploring, you have to abstract out the method, either as an interface or an abstract method. For example:
class abstract Animal {
abstract void communicate();
}
class Dog extends Animal {
void communicate() {
System.out.println("bark");
}
}
class Human extends Animal {
void communicate() {
System.out.println("talk");
}
}

As Gaurav says you have to create a reference to Human or cast Animal to Human. But inheritance would make more sense if Animal were an interface or an abstract class (What I don't particularly like to do) and exposed a method in which all derived classes should have to implement.
public interface Animal {
String getName();
int getAge();
void blab();
}
public class Human implements Animal {
private String name;
private int age;
Human(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
public void blab() {
System.out.println("Talk");
}
}
And the main
public class Program {
public static void main(String[] args) {
Animal animal = new Human("Bob", 1);
animal.blab();
}
}

Related

Java Inheritance: Calling a subclass method in a superclass

I'm very new to java and would like to know whether calling a subclass method in a superclass is possible. And if doing inheritance, where is the proper place to set public static void main.
Superclass
public class User {
private String name;
private int age;
public User() {
//Constructor
}
//Overloaded constructor
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public static void main(String []args) {
User user1 = new Admin("Bill", 18, 2);
System.out.println("Hello "+user1.getName());
user1.getLevel();
}
}
Subclass
public class Admin extends User {
private int permissionLevel;
public Admin() {
//Constructor
}
//Overloading constructor
public Admin(String name, int age, int permissionLevel) {
super(name, age);
this.permissionLevel = permissionLevel;
}
public void getLevel() {
System.out.println("Hello "+permissionLevel);
}
}
Short answer: No.
Medium answer: Yes, but you have to declare the method in the superclass. Then override it in the subclass. The method body from the subclass will be in invoked when the superclass calls it. In your example, you could just put an empty getLevel method on User.
You could also consider declaring User as an abstract class and declaring the getLevel method as abstract on the User class. That means you don't put any method body in getLevel of the User class but every subclass would have to include one. Meanwhile, User can reference getLevel and use the implementation of its subclass. I think that's the behavior you're going for here.
I'm very new to java and would like to know whether calling a subclass
method in a superclass is possible.
A superclass doesn't know anything about their subclasses, therefore, you cannot call a subclass instance method in a super class.
where is the proper place to set public static void main.
I wouldn't recommend putting the main method in the Admin class nor the User class for many factors. Rather create a separate class to encapsulate the main method.
Example:
public class Main{
public static void main(String []args) {
User user1 = new Admin("Bill", 18, 2);
System.out.println("Hello "+user1.getName());
user1.getLevel();
}
}
No, it is not possible to call sub class method inside super class.
Though it is possible to call different implementations of the same method in a client code while you have a variable with a super class type and instantiate it with either super class or sub class objects. It is called polymorphism.
Please, consider the following example:
public class User {
private String name;
private int age;
protected int permissionLevel;
public User() {
//Constructor
}
//Overloaded constructor
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public void getLevel() {
System.out.println("Hello "+ permissionLevel);
}
}
public class Admin extends User {
public Admin() {
//Constructor
}
//Overloading constructor
public Admin(String name, int age, int permissionLevel) {
super(name, age);
this.permissionLevel = permissionLevel;
}
#Override
public void getLevel() {
System.out.println("Hello "+permissionLevel);
}
public static void main(String []args) {
User user1 = new Admin("Bill", 18, 2);
System.out.println("Hello "+user1.getName());
user1.getLevel(); //call to subclass method
user1 = new User("John", 22); //the variable is the same but we assign different object to it
user1.getLevel(); //call to superclass method
}
}
Answering your second question, no, it does not matter where you place your main method as long as it is of right method signature. As you can see in my example I moved the method to Admin.java - it is still acceptable.
Calling subclass method in a superclass is possible but calling a subclass method on a superclass variable/instance is not possible.
In java all static variable and methods are considered to be outside the class i.e they do have access to any instance variable or methods. In your example above it will be wise to create a new class called Main and put public static void main in there but this is just a hygiene issue and what you have above will work except for the line.
user1.getLevel()
Use case: If employee eats, then automatically should sleep:-)
Declare two methods eat and sleep from class person.
Invoke the sleep method from eat.
Extend person in the employee class and override only the sleep method:
Person emp=new Employee();
emp.eat();
Explanation: As eat method is not in subclass, it will invoke the super class eat. From there, sub class's sleep will be invoked.

How to call a method in an abstract class properly

public abstract class Human{
public String name;
public int number
public void getInfo(){
Name = JOptionPane.showInputDialog("Please enter your name: ");
money = Double.parseDouble(JOptionPane.showInputDialog("Please enter amount of money .00: "));
}
public void displayInfo(){
JOptionPane.showMessageDialog(null,"Name: "+name+"\n"+
"Number: "+number);
}
}
public class Student extends Human {
}
public class Teacher extends Human{
}
public class Janitor extends Human{
{
I need help if calling the methods getInfo() and displayInfo() in all 3 classes below. I have tried:
public class Student extends Human{
public Student(){
getInfo();
displayInfo();
}
it works, but it generates a warning saying "problematic call in constructor" I guess it is not the best way to do it.
I also tried:
#Override
public void getInfo() {
}
but if I leave it empty nothing happens. Basically I am trying to call the method in the abstract class in a simple way without needing to type it up in every class.
As already mentioned, you shouldn't call overridable methods in constructors, because if another class overrides this method and invokes the constructor of the superclass, it may try to use values that are not initialized yet, since the overriden method will be invoked. Example:
public class Superclass {
protected int id;
protected void foo() {
System.out.println("Foo in superclass");
}
public Superclass() {
foo();
}
}
public class Subclass extends Superclass {
public Subclass(int id) {
super();
this.id = id;
}
#Override
protected void foo() {
System.out.println("Id is " + id);
}
}
This will print the unitialized value of id, since you first call the constructor of the superclass which invokes the foo method of the subclass.
You can fix this by making your methods final if this suits your case.
You get the warning because it's a good practice not to call overridables in the constructor; since these overridables could try to access member variables that are not initialized yet (== null) .
You shouldn't call overridable functions inside a constructor. check this link

Iinherited fields value are not changed

I'm not sure if these question is still appropriate to be asked as there could be an answer already. But i still dont understand the concept of inheritance when it comes to attributes in parent and child class relationship. Please note the example below.
class Animal{
public int lifeSpan = 50;
public String imAn(){
return "I'm an Animal";
}
}
class Elephant extends Animal{
public int lifeSpan = 100;
public String imAn(){
return "I'm an Elephant";
}
}
public class Test{
public static void main(String args[]){
Animal animal = new Elephant();
System.out.println(animal.imAn()+" and i live around "+animal.lifeSpan+" years");
}
}
Answer would be : I'm an Elephant and i live around 50 years.
I do understand the virtual method invocation concept here, but what makes it not load the lifeSpan attribute of child class. Does this means the class attributes are not polymorphic?
Does this means the class attributes are not polymorphic?
No, fields aren't polymorphic. You've actually got two fields in your Elephant class - one declared in Animal and one declared in Elephant, which hides the one in Animal. That's the problem. You should get rid of the declaration of lifeSpan in Elephant, and instead initialize the one remaining field in a constructor.
You should also get into the habit of making fields private - and final, where possible. Assuming you really want to have a method to describe the name (rather than a field, which would be more usual) I would write your code as:
class Animal {
private final int lifeSpan;
public Animal() {
// Default to a life-span of 50
this(50);
}
public Animal(int lifeSpan) {
this.lifeSpan = lifeSpan;
}
public String getName(){
return "Animal";
}
public int getLifeSpan() {
return lifeSpan;
}
}
class Elephant extends Animal {
public Elephant() {
// Give every elephant a life-span of 100.
super(100);
}
#Override public String getName() {
return "Elephant";
}
}
public class Test {
public static void main(String args[]){
Animal animal = new Elephant();
System.out.printf("I am an %s and I live around %d years%n",
animal.getName(), animal.getLifeSpan());
}
}

No suitable Constructor Found

This is my code and i am trying to pass the parameter from main to cat class but its saying no constructor cant figure out what to do a little help would be appreciated.
public class Cat extends Animal implements Pet {
public String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Cat(String name, int legs) {
super(4);
this.name = name;
}
public Cat() {
this("Fluppy"); //ERROR OVER HERE
}
#Override
public void play() { //THIS METHOD IS OVERRIDDEN FROM PET INTERFACE
System.out.println(name+"Likes to play with string");
}
#Override
public void eat() { /*THIS METHOD IS OVERRIDDEN FROM ANIMAL ABSTRACT METHOD.*/
System.out.println("Cats likes to eat spiders and fish");
}
}
and the main class
public class PetMain {
public static void main(String[] args) {
Animal a;
Pet p;
Cat c= new Cat("Tom"); //IM GETTING THE ERROR OVER HERE.
c.eat();
c.walk();
c.play();
}
}
try using the correct constructor which takes two parameters
Cat c= new Cat("Tom", 4);
and
this("Fluppy", 4);
or make a new constructor for one parameter like
public Cat(String name) {
this (name, 4);
}
Take a look at your constructors in Cat
public Cat(String name, int legs) { // accept String and int constructor
super(4);
this.name = name;
}
public Cat() { // no argument constructor
this("Fluppy");
}
There is no matching for new Cat("String")
You can add new constructor
public Cat(String anyThing) {
}
First thing when you call this
Cat c= new Cat("Tom");
It expects that you Cat class have a single argument constructor which your class doesnot contain so create a single argument constructor in your Cat class like this
public Cat(String str) {
// your logic
}
Secondly this("Fluppy"); //ERROR OVER HERE
If you know about constructor chaining then you would not have done this. this() is usually used when you want to call another constructor of the same class from within one constructor in your case you are calling one-parameterized constructor from you default constructor since one-parameterized constructor doesnot exist it is giving you compilation error
You are trying to overload the constructor at:
public Cat() {
this("Fluppy"); //ERROR OVER HERE
}
but the call made is for the constructor with one String argument. You do not have a constructor with one String argument , So you have an error try to add.
public Cat(String catty) {
// initialise
}

Is there a way to override class variables in Java?

class Dad
{
protected static String me = "dad";
public void printMe()
{
System.out.println(me);
}
}
class Son extends Dad
{
protected static String me = "son";
}
public void doIt()
{
new Son().printMe();
}
The function doIt will print "dad". Is there a way to make it print "son"?
In short, no, there is no way to override a class variable.
You do not override class variables in Java you hide them. Overriding is for instance methods. Hiding is different from overriding.
In the example you've given, by declaring the class variable with the name 'me' in class Son you hide the class variable it would have inherited from its superclass Dad with the same name 'me'. Hiding a variable in this way does not affect the value of the class variable 'me' in the superclass Dad.
For the second part of your question, of how to make it print "son", I'd set the value via the constructor. Although the code below departs from your original question quite a lot, I would write it something like this;
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public void printName() {
System.out.println(name);
}
}
The JLS gives a lot more detail on hiding in section 8.3 - Field Declarations
Yes. But as the variable is concerned it is overwrite (Giving new value to variable. Giving new definition to the function is Override). Just don't declare the variable but initialize (change) in the constructor or static block.
The value will get reflected when using in the blocks of parent class
if the variable is static then change the value during initialization itself with static block,
class Son extends Dad {
static {
me = "son";
}
}
or else change in constructor.
You can also change the value later in any blocks. It will get reflected in super class
Yes, just override the printMe() method:
class Son extends Dad {
public static final String me = "son";
#Override
public void printMe() {
System.out.println(me);
}
}
You can create a getter and then override that getter. It's particularly useful if the variable you are overriding is a sub-class of itself. Imagine your super class has an Object member but in your sub-class this is now more defined to be an Integer.
class Dad
{
private static final String me = "dad";
protected String getMe() {
return me;
}
public void printMe()
{
System.out.println(getMe());
}
}
class Son extends Dad
{
private static final String me = "son";
#Override
protected String getMe() {
return me;
}
}
public void doIt()
{
new Son().printMe(); //Prints "son"
}
If you are going to override it I don't see a valid reason to keep this static. I would suggest the use of abstraction (see example code). :
public interface Person {
public abstract String getName();
//this will be different for each person, so no need to make it concrete
public abstract void setName(String name);
}
Now we can add the Dad:
public class Dad implements Person {
private String name;
public Dad(String name) {
setName(name);
}
#Override
public final String getName() {
return name;
}
#Override
public final void setName(String name) {
this.name = name;
}
}
the son:
public class Son implements Person {
private String name;
public Son(String name) {
setName(name);
}
#Override
public final String getName() {
return name;
}
#Override
public final void setName(String name) {
this.name = name;
}
}
and Dad met a nice lady:
public class StepMom implements Person {
private String name;
public StepMom(String name) {
setName(name);
}
#Override
public final String getName() {
return name;
}
#Override
public final void setName(String name) {
this.name = name;
}
}
Looks like we have a family, lets tell the world their names:
public class ConsoleGUI {
public static void main(String[] args) {
List<Person> family = new ArrayList<Person>();
family.add(new Son("Tommy"));
family.add(new StepMom("Nancy"));
family.add(new Dad("Dad"));
for (Person person : family) {
//using the getName vs printName lets the caller, in this case the
//ConsoleGUI determine versus being forced to output through the console.
System.out.print(person.getName() + " ");
System.err.print(person.getName() + " ");
JOptionPane.showMessageDialog(null, person.getName());
}
}
}
System.out Output : Tommy Nancy Dad
System.err is the same as above(just has red font)
JOption Output: Tommy then Nancy then Dad
This looks like a design flaw.
Remove the static keyword and set the variable for example in the constructor. This way Son just sets the variable to a different value in his constructor.
Though it is true that class variables may only be hidden in subclasses, and not overridden, it is still possible to do what you want without overriding printMe () in subclasses, and reflection is your friend. In the code below I omit exception handling for clarity. Please note that declaring me as protected does not seem to have much sense in this context, as it is going to be hidden in subclasses...
class Dad
{
static String me = "dad";
public void printMe ()
{
java.lang.reflect.Field field = this.getClass ().getDeclaredField ("me");
System.out.println (field.get (null));
}
}
https://docs.oracle.com/javase/tutorial/java/IandI/hidevariables.html
It's called Hiding Fields
From the link above
Within a class, a field that has the same name as a field in the superclass hides the superclass's field, even if their types are different. Within the subclass, the field in the superclass cannot be referenced by its simple name. Instead, the field must be accessed through super, which is covered in the next section. Generally speaking, we don't recommend hiding fields as it makes code difficult to read.
class Dad
{
protected static String me = "dad";
public void printMe()
{
System.out.println(me);
}
}
class Son extends Dad
{
protected static String _me = me = "son";
}
public void doIt()
{
new Son().printMe();
}
... will print "son".
It indeed prints 'dad', since the field is not overridden but hidden. There are three approaches to make it print 'son':
Approach 1: override printMe
class Dad
{
protected static String me = "dad";
public void printMe()
{
System.out.println(me);
}
}
class Son extends Dad
{
protected static String me = "son";
#override
public void printMe()
{
System.out.println(me);
}
}
public void doIt()
{
new Son().printMe();
}
Approach 2: don't hide the field and initialize it in the constructor
class Dad
{
protected static String me = "dad";
public void printMe()
{
System.out.println(me);
}
}
class Son extends Dad
{
public Son()
{
me = "son";
}
}
public void doIt()
{
new Son().printMe();
}
Approach 3: use the static value to initialize a field in the constructor
class Dad
{
private static String meInit = "Dad";
protected String me;
public Dad()
{
me = meInit;
}
public void printMe()
{
System.out.println(me);
}
}
class Son extends Dad
{
private static String meInit = "son";
public Son()
{
me = meInit;
}
}
public void doIt()
{
new Son().printMe();
}
Variables don't take part in overrinding. Only methods do. A method call is resolved at runtime, that is, the decision to call a method is taken at runtime, but the variables are decided at compile time only. Hence that variable is called whose reference is used for calling and not of the runtime object.
Take a look at following snippet:
package com.demo;
class Bike {
int max_speed = 90;
public void disp_speed() {
System.out.println("Inside bike");
}
}
public class Honda_bikes extends Bike {
int max_speed = 150;
public void disp_speed() {
System.out.println("Inside Honda");
}
public static void main(String[] args) {
Honda_bikes obj1 = new Honda_bikes();
Bike obj2 = new Honda_bikes();
Bike obj3 = new Bike();
obj1.disp_speed();
obj2.disp_speed();
obj3.disp_speed();
System.out.println("Max_Speed = " + obj1.max_speed);
System.out.println("Max_Speed = " + obj2.max_speed);
System.out.println("Max_Speed = " + obj3.max_speed);
}
}
When you run the code, console will show:
Inside Honda
Inside Honda
Inside bike
Max_Speed = 150
Max_Speed = 90
Max_Speed = 90
only by overriding printMe():
class Son extends Dad
{
public void printMe()
{
System.out.println("son");
}
}
the reference to me in the Dad.printMe method implicitly points to the static field Dad.me, so one way or another you're changing what printMe does in Son...
You cannot override variables in a class. You can override only methods. You should keep the variables private otherwise you can get a lot of problems.
No. Class variables(Also applicable to instance variables) don't exhibit overriding feature in Java as class variables are invoked on the basis of the type of calling object. Added one more class(Human) in the hierarchy to make it more clear. So now we have
Son extends Dad extends Human
In the below code, we try to iterate over an array of Human, Dad and Son objects, but it prints Human Class’s values in all cases as the type of calling object was Human.
class Human
{
static String me = "human";
public void printMe()
{
System.out.println(me);
}
}
class Dad extends Human
{
static String me = "dad";
}
class Son extends Dad
{
static String me = "son";
}
public class ClassVariables {
public static void main(String[] abc) {
Human[] humans = new Human[3];
humans[0] = new Human();
humans[1] = new Dad();
humans[2] = new Son();
for(Human human: humans) {
System.out.println(human.me); // prints human for all objects
}
}
}
Will print
human
human
human
So no overriding of Class variables.
If we want to access the class variable of actual object from a reference variable of its parent class, we need to explicitly tell this to compiler by casting parent reference (Human object) to its type.
System.out.println(((Dad)humans[1]).me); // prints dad
System.out.println(((Son)humans[2]).me); // prints son
Will print
dad
son
On how part of this question:- As already suggested override the printMe() method in Son class, then on calling
Son().printMe();
Dad's Class variable "me" will be hidden because the nearest declaration(from Son class printme() method) of the "me"(in Son class) will get the precedence.
Just Call super.variable in sub class constructor
public abstract class Beverage {
int cost;
int getCost() {
return cost;
}
}`
public class Coffee extends Beverage {
int cost = 10;
Coffee(){
super.cost = cost;
}
}`
public class Driver {
public static void main(String[] args) {
Beverage coffee = new Coffee();
System.out.println(coffee.getCost());
}
}
Output is 10.
Of course using private attributes, and getters and setters would be the recommended thing to do, but I tested the following, and it works... See the comment in the code
class Dad
{
protected static String me = "dad";
public void printMe()
{
System.out.println(me);
}
}
class Son extends Dad
{
protected static String me = "son";
/*
Adding Method printMe() to this class, outputs son
even though Attribute me from class Dad can apparently not be overridden
*/
public void printMe()
{
System.out.println(me);
}
}
class Tester
{
public static void main(String[] arg)
{
new Son().printMe();
}
}
Sooo ... did I just redefine the rules of inheritance or did I put Oracle into a tricky situation ?
To me, protected static String me is clearly overridden, as you can see when you execute this program. Also, it does not make any sense to me why attributes should not be overridable.
Why would you want to override variables when you could easily reassign them in the subClasses.
I follow this pattern to work around the language design. Assume a case where you have a weighty service class in your framework which needs be used in different flavours in multiple derived applications.In that case , the best way to configure the super class logic is by reassigning its 'defining' variables.
public interface ExtensibleService{
void init();
}
public class WeightyLogicService implements ExtensibleService{
private String directoryPath="c:\hello";
public void doLogic(){
//never forget to call init() before invocation or build safeguards
init();
//some logic goes here
}
public void init(){}
}
public class WeightyLogicService_myAdaptation extends WeightyLogicService {
#Override
public void init(){
directoryPath="c:\my_hello";
}
}

Categories