Accessing super class variables/methods in sub class - java

Since subclass can access super class's variables and methods defined as protected, why following code gives compile error?
public class Animal {
protected int var;
public void eat() {
System.out.println("Animal eating");
}
}
class Dog extends Animal {
Animal an = new Animal();
an.var = 10;
}

The Problem is not caused by the fact that var is protected. It is because you need to wrap up that line in a method, like this
public Dog(){
an.var = 10; //Compiles Correctly
}

You need to put it inside a Method. See below :
class Dog extends Animal {
public void testMe()
{
Animal an = new Animal();
an.var = 10;
}
}

If you want the Dog class to have the var attribute set by default, you can use the constructor:
public class Dog extends Animal {
public Dog() {
this.var=10;
}
}
or use:
Dog dog = new Dog();
dog.var=11;

Related

Inheritance not allowing me to create an object of subclass?

class Animal {
String type;
int size;
public Animal(String name, int size)
{
this.type = name;
this.size = size;
}
public Animal ()
{
}
public void run() {
System.out.println("I can run!");
}
}
class Cat extends Animal {
String color;
public void meow() {
System.out.println("I can meow!");
}
}
public class HelloWorld{
public static void main(String []args){
Animal cat = new Cat();
cat.meow();
cat.run();
}
}
Why is it when I try to create a new Cat object from the superclass Animal, I get an error with the .meow() part of the code. Specifically "error: cannot find symbol cat.meow();" . Aren't I creating a Cat object so shouldn't it have access to the methods in there?
Animal is the base class. If you extend Animal you can add additional methods and instance variables in that class, which you actually did correctly.
As soon as you instantiate a child class (class that extends the base class, e.g.: new Cat()) but assign it to the type of the base class (Animal) you can only call the methods that are available there, i.e. in your case you could only call methods that are declared in the Animal class.
Lets assume you have a class Animal :
public class Animal {
public void makeSound() {
System.out.println("Default sound");
}
}
Now you create a class Cat that extends Animal:
public class Cat extends Animal {
private int catProperty = 5;
//Override method of base class
public void makeSound() {
System.out.println("Meow");
}
public int getCatProperty(){
return this.catProperty;
}
}
An another class called Dog that extends Animal:
public class Dog extends Animal {
private int dogProperty = 8;
//Override method of base class
public void makeSound() {
System.out.println("Woof");
}
public int getDogProperty(){
return this.dogProperty;
}
}
Since Animal is the base class you can now create an array of type Animal which holds Cats and Dogs.
Animal[] animals = new Animal[2];
animals[0] = new Cat();
animals[1] = new Dog();
for (Animal animal : animals) {
animal.makeSound();
}
Each of the animals (Cat and Dog) will now print the proper sound.
In case you really need to call a child class specific method, you have to cast the object back to an instance of that child class. In that case you have to be sure of what type the child class is.
E.g.:
for (Animal animal : animals) {
// Calls overriden method
animal.makeSound();
// This is illegal. Method getCatProperty is not declared in Animal
animal.getCatProperty();
// This is illegal. Method getDogProperty is not declared in Animal class
animal.getDogProperty();
/*
* IF YOU HAVE TO CALL CHILD CLASS SPECIFIC METHODS, DO IT LIKE THIS:
*/
// Checks if animal is of type Cat
if (animal instanceof Cat) {
// Casts animal to instance of Cat
Cat cat = (Cat) animal;
// Calls specific Cat instance method
System.out.println(cat.getCatProperty());
}
// Checks if animal is of type Dog
if (animal instanceof Dog) {
// Casts animal to instance of Dog
Dog dog = (Dog) animal;
// Calls specific Dog instance method
System.out.println(dog.getDogProperty());
}
}
Just as a sidenote: If you plan not to directly create instances of Animal (Animal a = new Animal()), you should declare the class itself and the methods that should be overriden by child classes as abstract.
public abstract class Animal {
public abstract void makeSound();
}
Also, in case that base class only has methods and no instance variables that should be available to the child classes, it's probably better use an interface instead of a (abstract) class.
public interface Animal {
public abstract void makeSound();
}
The interface then has to be implemented (not extended) by the concrete class.
public class Cat implements Animal {
public void makeSound() {
System.out.println("Meow");
}
}
Hope this helps!
Animal cat = new Cat()
The compiler "forgets" that you created a Cat instance.
Your sourcecode says: I have a variable named cat that is an instance of Animal.
There is no method meow() on the Animal class.
If you want to call a subclass method, you need a subclass instance:
Cat cat = new Cat();
cat.meow();
or you need to cast. Basically you tell the compiler: "I know better than you".
Animal cat = new Cat();
( (Cat) cat).meow();
The point is: java is statically typed. In python, the interpreter would just see if that cat thingy has a method called meow() that it could call. Doesn't work like that in Java.

How to use reflection with multiple classes extending the base class in java

I am very new to reflections and I would like to get some advices/help. I am trying to get the subclass names using reflection in the base class. I have multiple subclasses (Cat, Dog, Frog etc..) and all of them extend the base class (Animal).
What I want to do is getting the class names from the subclasses themselves and pass them through the constructors so the Animal does not have to instantiate dozens of subclasses. Below is an example of what I am NOT trying to do.
If there is a way to just dynamically get the subclasses names without going through the pain of instantiating every single subclass, I would love to see it. Your help is much appreciated.
class Dog extends Animal {
private String s;
public Dog() {
s = "Bark";
}
public void method() {
System.out.println("Dogs " + s);
}
}
class Cat extends Animal {
private String s;
public Cat() {
s = "Meow";
}
public void method() {
System.out.println("Cats " + s);
}
}
class Animal {
public static void main(String args[]) throws Exception {
Dog dog = new Dog();
Cat cat = new Cat();
Class cls = dog.getClass();
System.out.println("The name of class is " + cls.getName());
Constructor constructor = cls.getConstructor();
System.out.println("The name of constructor is " + constructor.getName());
}
}
I do not see why you want the names of the subclasses. If the problem is to instantiate a class based on its name it would be better to use an Abstract Factory pattern. You can create an enumeration that contains the animal that you knows
enum ANIMALS {
DOG, CAT
}
You can create the Animal interface
public interface Animal {
}
the classes extending Animal as default classes
public class Dog implements Animal {
}
then finally the AnimalAbstractFactory as
public class AnimalAbstractFactory {
public enum ANIMALS {
DOG, CAT
}
public Animal createAnimal(ANIMALS animal) {
switch (animal) {
case DOG:
return new Dog();
case CAT:
return new Cat();
}
return null;
}
}
Notes that now you do not need to know the subclass to instantiate an animal. Note also that createAnimal returns an Animal not the subclass. I hope it helps.

dynamic polymorphism

class Test {
public static void main(String[] args) {
Animal a = new Dog();
Dog d = new Dog();
d.makeNoise(); // output "Sub"
a.makeNoise(); // output "Sub" then what is use of calling this. why not call d.makeNoise() only.
}
}
abstract class Animal {
public void makeNoise() {
System.out.println("Super");
}
}
class Dog extends Animal {
#Override
public void makeNoise() {
System.out.println("Sub");
}
}
We had 15 minutes discussion over this topic(15 minutes is too long I guess) I explained interviewer about how dynamic polymorphism will be achieved with the help of a.makeNoise(); but still she was saying both are giving same output.
a.makeNoise(); output "Sub" then what is use of calling this. why not call d.makeNoise() only
I went to interface also but still question was if subclass reference is giving same output then why to use superclass reference.
Interviewer question was, what difference a.makeNoise(); makes? why not call d.makeNoise(); only when both are giving same output?
What could be the possible correct answer?
Animal a = new Dog(); // this animal is a dog
Dog d = new Dog(); // this dog is a dog
A dog is a dog, however you declared it.
a.getClass() equals d.getClass() equals Dog.class.
On the other hand:
Animal a = new Animal(); // this animal is an animal
a.makeNoise(); // prints "Super"
The example below illustrates dynamic polymorphism. Both a and d are declared to be Animals, but d is actually a dog.
Notice that when I call makeNoise on the Animal d, java will know that d is actually a dog and not just any animal.
class Test {
public static void main(String[] args) {
Animal a = new Animal();
Animal d = new Dog();
d.makeNoise(); // output "Bark" - d is an animal that barks
a.makeNoise(); // output "Squawk" - a is an animal that squawks
}
}
class Animal {
public void makeNoise() {
System.out.println("Squawk");
}
}
class Dog extends Animal {
#Override
public void makeNoise() {
System.out.println("Bark");
}
}
This is the reason-
Animal a = new Dog();
Animal is dog so noise would be same :)
If create another animal, say Cat, with that method, and point animal to Cat, you should get a different noise.
Your simplified example does not present the case well enough.
Collection<Animal> caged = getCagedAnimals();
for (Animal a : caged)
a.makeNoise();
As there are many types of animals (classes), each makes a different noise. We do not need any typecasting to obtain different behavior, so to say. Imagine the horrors which would happen if we would want each animal to make a noise without polymorphism:
for (Animal a : caged) {
if (a instanceof Dog)
((Dog)a).woof(); // or, ((Dog)a).makeNoise()
else if (a instanceof Cat)
((Cat)a).meow(); // or, ((Cat)a).makeNoise()
else {...}
}
Let us have an object of type T. We are trying to invoke toString() (defined by Object class)
Dynamic method invocation proceeds as follows (actually, a virtual method table is used):
C = T
do
if (C defines toString()) {
call T.toString()
break
}
C = superclass of C
while (C != null)
throw new NoSuchMethodError();
Now, if we have
Object obj = new T();
and we call
obj.toString();
we are actually calling toString() of class T.
consider there are 3 classes
animal
dog
cat
cat and dog are sub classes of animal.
class Test {
public static void main(String[] args) {
Animal a = new Animal();
int user_input=userinput(); //returns 1 for cat and 2for dog
switch(user_input)
{
case 1:Animal d=new Cat();
break;
case 2: Animal d=new Dog();
break;
}
d.makeNoise(); // output "Bark"/"meow" as per user input(dynamic linking)
a.makeNoise(); // output "Squawk" - a is an animal that squawks
}
}
class Animal {
public void makeNoise() {
System.out.println("Squawk");
}
}
class Cat extends Animal {
#Override
public void makeNoise() {
System.out.println("meow");
}
}
class Dog extends Animal {
#Override
public void makeNoise() {
System.out.println("Bark");
}
}
class Account {
public static void main(String[] args) {
Animal a = new Dog();
Dog d = new Dog();
d.makeNoise();
a.makeNoise();
a = new Cat();
a.makeNoise();
}
}
abstract class Animal {
public void makeNoise() {
System.out.println("Super");
}
}
class Dog extends Animal {
public void makeNoise() {
System.out.println("Sub");
}
}
class Cat extends Animal {
}
See the above modified example and the observations
We have an abstract class Animal with an implementation for makeNoise (let me say default implementation here)
We have a Dog class which is of Type animal but has a customized makeNoise methods
We have a Cat Class which is of Type animal but has no customized makeNoise methods. it uses default makeNoise of Animal type.
if I use Animal a = new Dog() and a.makeNoise(), then I can remove my makenoise method from Dog class whenever I wish with no changes to any other class. It will still compile and execute without any error.
if I use Dog d = new Dog() and d.makeNoise(), then I cannot remove my makenoise method from Dog class whenever I wish. if I do, I also need to change the main class for the application to compile.
i will give one general ex:- personA has one bank account he has all permissions on that account(withdraw,deposit,loanetc). personB wants to deposit money into personA account in this time he wants to access personA's account but we have to provide deposit permissions only.
class perosnB
{
public void deposit()
{
................
}
}
class personA extends personB
{
public void deposit()
{
......
}
public void withdraw()
{
......
}
}
personA p=new personB();
PersonB p2=new personB();
by using p object we can access only withdraw method. by using p2 we can access deposit also.
weather personA class is abstract or not. if personA is abstract class creating object for personA class is not possible( personA p=new personA()) . personA p=new personB() is possible.
Animal a = new Dog();
a is a a reference of type Animal but it refers to the object of type Dog.
Here Dog overrides makeNoise() method of Animal class.
class Animal {
public void makeNoise() {
System.out.println("Squawk");
}
}
class Dog extends Animal {
#Override
public void makeNoise() {
System.out.println("Bark");
}
}
Since object is of Dog class JVM will bind Dog class' makeNoise() method to the object and binding will be done at runtime.
so the Output of
a.makeNoise();
will be
sub

If I've cast a subclass as its superclass, and call a method that was overridden in the subclass, does it perform the overridden or original method?

Consider:
Dog is a subclass of Animal, and Dog overrides Animal.eat()
Animal[] animals = getAllAnimals();
for (int i = 0; i < animals.length; i++) {
animals[i].eat();
}
If Animal.eat() is overriden by Dog.eat(), which one is called when the method is called from an identifier of type Animal (animals[i]?)
The subclass method will be called. That's the beauty of polymorphism.
The subclass will be the only method call, unless the subclass calls the superclass like this:
class Dog {
public eat() {
super.eat();
}
}
The code
Animal a = new Dog();
a.eat();
will call Dog's eat method. But beware! If you had
class Animal {
public void eat(Animal victim) {
System.out.println("Just ate a cute " + victim.getClass().getSimpleName());
}
}
and you have a Cat that defines an additional method:
class Cat extends Animal {
public void eat(Mouse m) { System.out.println("Grabbed a MOUSE!"); }
}
and then you use them:
Animal cat = new Cat();
Animal mouse = new Mouse();
cat.eat(mouse);
This will print "Just ate a cute Mouse", and not "Grabbed a MOUSE!". Why? Because polymorphism only works for the object to the left of the dot in a method invocation.
It'll call the version in the subclass.
Inheritance would be pretty useless if you couldn't pass around a subclassed object cast as its superclass and not get the subclassed method!
A sscce
/**
* #author fpuga http://conocimientoabierto.es
*
* Inheritance test for http://stackoverflow.com/questions/10722447/
*
*/
public class InheritanceTest {
public static void main(String[] args) {
Animal animals[] = new Animal[2];
animals[0] = new Animal();
animals[1] = new Dog();
for (int i = 0; i < animals.length; i++) {
animals[i].eat();
if (animals[i] instanceof Dog) {
System.out.println("!!Its a dog instance!!");
((Dog) animals[i]).eat();
}
}
}
private static class Animal {
public void eat() {
System.out.println("I'm an animal");
}
}
private static class Dog extends Animal {
#Override
public void eat() {
System.out.println("I'm dog");
}
}
}

Java abstract class implements interface

I have the following interface and abstract class that implements it:
interface Walk {
String walk();
}
public abstract class Animal implements Walk {
abstract String MakeNoise();
}
And the following concrete implementations:
class Cat extends Animal {
String MakeNoise() {
return "Meow";
}
#Override
String walk() {
return "cat is walking";
}
}
class Dog extends Animal {
#Override
String walk() {
return "Dog is walking";
}
#Override
String MakeNoise() {
return "bark";
}
}
class Human {
public void Speak() {
System.out.println("...Speaking...");
}
}
Putting it all together:
class MainClass {
public static void main(String[] args) {
Random randomGen = new Random();
Animal[] zoo = new Animal[4];
zoo[0] = new Cat();
zoo[1] = new Dog();
zoo[2] = new Cat();
zoo[3] = new Cat();
// System.out.println(zoo[ randomGen.nextInt(2)].MakeNoise());
for (Animal animal : zoo) {
if (animal instanceof Dog) {
Dog jeffrey = (Dog) animal;
System.out.println(jeffrey.MakeNoise());
}
}
}
}
I get this error
"walk() in Cat cannot implement walk() in Walk " .
Any ideas? thanks
Methods in interfaces are implicitly public. However, methods in classes are package-visible by default. You cannot reduce the visibility of an overriden method, i.e. you can't do stuff like this:
class A {
public foo() {}
}
class B extends A {
private foo() {} // No!
}
class C extends A {
foo() {} // No! foo is package-visible, which is lower than public
}
In your case, the solution is to declare walk() as public in Dog and Cat.
The error eclipse gives is:
Cannot reduce the visibility of the inherited method from Walk
The method must be public, because it is defined in an interface.
Interface methods must be public. You need to declare walk() as a public method in Cat.
Make String walk() implementations public. That will fix it

Categories

Resources