Inheritance.java
public class InheritanceExample {
static public void main(String[] args){
Cat c = new Cat();
System.out.println(c.speak());
Dog d = new Dog();
System.out.println(d.speak());
}
}
Animal.java
public class Animal {
protected String sound;
public String speak(){
return sound;
}
}
Cat.java
public class Cat extends Animal {
protected String sound = "meow";
}
Dog.java
public class Dog extends Animal {
protected String sound = "woof";
}
Output:
null
null
My animals cannot speak. So sad.
Fields aren't polymorphic. You've declared three entirely distinct fields... the ones in Cat and Dog shadow or hide the one in Animal.
The simplest (but not necessarily best) way of getting your current code is to remove sound from Cat and Dog, and set the value of the inherited sound field in the constructor for Cat and Dog.
A better approach would be to make Animal abstract, and give it a protected constructor which takes the sound... the constructors of Cat and Dog would then call super("meow") and super("woof") respectively:
public abstract class Animal {
private final String sound;
protected Animal(String sound) {
this.sound = sound;
}
public String speak(){
return sound;
}
}
public class Cat extends Animal {
public Cat() {
super("meow");
}
}
public class Dog extends Animal {
public Dog() {
super("woof");
}
}
You cannot override class fields, only methods. The sound field in your Dog and Cat classes is actually hiding the sound field in the Animal superclass.
You can, however, access superclass fields from subclasses, so you could do something like this:
public class Dog extends Animal {
public Dog() {
sound = "woof";
}
}
public class Cat extends Animal {
public Cat() {
sound = "meow";
}
}
Or, you can make the Animal class abstract, and declare the speak method abstract too, then define it in subclasses:
public abstract class Animal {
public abstract String speak();
}
public class Dog extends Animal {
public String speak {
return "woof";
}
}
public class Cat extends Animal {
public String speak {
return "meow";
}
}
You're hiding fields. The sound in Animal is not the same String as the sound in Cat.
One possible solution is to create a constructor and there simply say
super.sound = "meow";
instead of in the class body saying
protected String sound = "meow";
to set the field.
A method will look in its own class' namespace to resolve fields. While methods defined in sub-classes can look up the hierarchy to resolve fields, the same is not true for classes defined higher up in the hierarchy, i.e., super-classes won't look down the hierarchy to resolve fields [and their values]
You're shadowing the field inherited from Animal. You have a few options, but the prettiest way of doing it is passing the sound in the constructor:
public class Animal {
private final String sound;
protected Animal(String sound){
if (sound == null)
throw new NullPointerException("sound");
this.sound = sound;
}
public String speak(){
return sound;
}
}
public class Cat extends Animal {
public Cat(){ super("meow"); }
}
public class Dog extends Animal {
public Dog(){ super("woof"); }
}
This way, you can make sure that an Animal always has a valid sound, right from construction.
The Java(TM) way is to declare the protected String getSound() in Animal.java and implement it in the subclasses.
You didn't allow your animals to speak!
you should do like this :
Cat.java:
public class Cat extends Animal {
// protected String sound = "meow";
public Cat(){
this.sound = "cat";
}
}
Dog.java:
public class Dog extends Animal {
// protected String sound = "woof";
public Dog(){
this.sound = "dog";
}
}
just because there are two members "sound" in Cat or Dog,and the one inherited from Animal
is hidden without value(so it prints null);another is special to Cat or Dog,which is assigned a value.
So you should use the pointer 'this' to quote the original member 'sound'.
Related
I'm trying to figure out whether implementing individual methods of a subclass in an abstract superclass, or casting is the better way to go about the following scenario.
Suppose I have an abstract class Animal which has two subclasses, Dog and Cat and a Main class where I save objects of Dog and Cat in an Animal array. The following is how I would go about using methods of the subclasses in a more generalized array.
class Main{
public static void main(String[] args){
Animal[] animalArray = new Animal[2];
animalArray[0] = new Cat();
animalArray[1] = new Dog();
for (Animal a : animalArray){
if (a.getClass().equals(Dog.class){
((Dog)a).bark();
} else {
((Cat)a).meow();
}
}
}
}
However a friend suggested that casting isn't best practice, and that I should define each method in the abstract superclass in the following way:
public abstract class Animal{
public abstract String meow(){
return null;
}
public abstract String bark();
return null;
}
}
After setting the return values of these methods to null I would need to use #Override and implement them in the respective subclasses.
Which way is better? I'm afraid the abstract class will be too large and will have methods assigned to subclasses that don't make sense (even if all they do is return null). I think by using casting I can make more precise uses of the methods.
meow() and bark() shouldn't be defined in the Animal class. These methods are specific to Cat and Dog classes.
You should define an abstract method as shown below, in the Animal class and override it in the sub classes.
public abstract class Animal {
public abstract String action() {};
}
public class Dog extends Animal {
#Override
public String action() {
//your implementation (bark)
}
}
public class Cat extends Animal {
#Override
public String action() {
//your implementation (meow)
}
}
Hope it answers your query.
I'm using Java 8 / Java 11. I have a type hierarchy (basically dtos or Java Beans) like
public abstract class Animal {
public abstract String getName();
public abstract int getAge();
}
And some imeplementations providing additional properties:
public class Dog extends Animal {
// implementation of abstract methods from base class animal
// additional properties
public String getSound() {
return "woof";
}
}
public class Dog extends Animal {
// implementation of abstract methods from base class animal
// additional properties
public String getSound() {
return "miaow";
}
}
public class Fish extends Animal {
// implementation of abstract methods from base class animal
// no implementaion for "getSound()"
}
Now, I'd like to process a Collection of Animals in a uniform way, e.g.
animals.forEach(x -> {
System.out.println(x.getName()); // works
System.out.println(x.getSound(); // doesn't work, as Fish is missing the method
});
I was wondering, what would be a good way to implement the "missing" methods assuming that they should return a default value like "n/a" for a String.
One obvious way would be to move all the missing methods to the base class and either declare them abstract or provide a default implementation.
But I'd like to have them more separate, i.e. making clear which properties were added for the "uniform processing".
Another way would be to introduce a helper class using instance of to determine, if the method is missing:
public class AnimalHelper {
public static String getSoundOrDefault(Animal animal) {
if (animal instanceof Dog) {
return ((Dog)animal).getSound();
}
if (animal instanceof Cat) {
return ((Cat)animal).getSound();
}
return "n/a";
}
}
which then gets called with an Animal:
System.out.println(AnimalHelper.getSoundOrDefault(animal));
This works, but the caller must now which methods to call on Animal directly and for which methods to use the helper.
Another solution, I came up with the adding an interface AnimalAdapter using the Java 8 feature of default implementation:
public interface AnimalAdapter {
default String getSoundOrDefault() {
return "n/a";
}
}
And adding it to the Animal class:
public abstract class Animal implements AnimalAdapter {
...
which results in adding the getSoundOrDefault() method in Dog and Cat, but not Fish:
public class Dog extends Animal {
...
#Override
public String getSoundOrDefault() {
return getSound();
}
}
(likewise in Cat).
Any comments on the above considerations or other ideas would be highly appreciated.
All what you have mentioned above as solutions are really good. But I take advantage to add more one solution based on polymorphism technic, and I think it's more simple and less expensive in terms of code.
Simply I'm gonna use Object.toString() method to display all needed parameters, so first of all you have to #Override toString() method as follow:
public class Dog extends Animal {
// implementation of abstract methods from base class animal
// additional properties
public String getSound() {
return "woof";
}
#Override
public String toString() {
return getName() + "\n" + getSound();
}
}
public class Fish extends Animal {
// implementation of abstract methods from base class animal
// no implementaion for "getSound()"
#Override
public String toString() {
return getName() + "\n" + "n/a";
}
}
public class Main {
public static void main(String[] args) {
Collection<Animal> animals = new ArrayList<>(2);
animals.add(new Dog());
animals.add(new Fish());
animals.forEach(System.out::println);
}
}
And here is the result:
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.
Assume that I've the following classes:
1) Animal class, a base class
public abstract class Animal {
public abstract void Hello();
}
2) Dog class, extends from Animal class
public class Dog extends Animal {
#Override
public void Hello() {
System.out.println("I'm Dog");
}
}
3) Wolf class, extends from Animal class
public class Wolf extends Animal {
#Override
public void Hello() {
System.out.println("I'm Wolf");
}
}
In the Dog class's constructor or newInstance method, is there a way to switch/turn itself into a Wolf class under a certain condition, say during full moon? So, basically, if the caller does something like below, the variable "a" will be a Wolf object during full moon, instead of a Dog object.
Animal a = (Animal) Class.forName("Dog").newInstance();
You could use a wrapper for Animal to delegate to the actual Animal you wish to track and; then include in the delegator wrapper a method to swap delegates based on the class name of the Animal you want. Here is an example class:
public abstract class Animal {
public abstract String hello();
static class Dog extends Animal {
#Override
public String hello() {
return "I'm Dog";
}
}
static class Wolf extends Animal {
#Override
public String hello() {
return "I'm Wolf";
}
}
static class AnimalWrapper extends Animal {
private Animal delegate = new Dog();
public void delegateTo(String className) throws Exception {
this.delegate = (Animal) Class.forName(className).newInstance();
}
#Override
public String hello() {
return delegate.hello();
}
}
public static void main(String[] args) throws Exception {
AnimalWrapper animal = new AnimalWrapper();
System.out.println("Animal says: " + animal.hello());
animal.delegateTo(Wolf.class.getName());
System.out.println("Animal says: " + animal.hello());
animal.delegateTo(Dog.class.getName());
System.out.println("Animal says: " + animal.hello());
}
}
Complete code on GitHub
You cannot do that.
It looks like you need something like factory (search for factory design pattern) that will be responsible for creating instance of class you need.
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