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
Related
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.
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;
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'.
Of course, the following doesn't work in Java (no abstract static methods)...
public abstract class Animal {
public abstract static Animal getInstance(byte[] b);
}
public class Dog extends Animal {
#Override
public static Dog getInstance(byte[] b) {
// Woof.
return new Dog(...);
}
}
public class Cat extends Animal {
#Override
public static Cat getInstance(byte[] b) {
// Meow.
return new Cat(...);
}
}
What's the correct way of requiring that Animal classes have a static getInstance method that instantiates itself? This method should be static; a "normal" abstract method doesn't make sense here.
There is no way to specify in an abstract class (or interface) that an implementing class must have a particular static method.
It is possible to get a similar effect using reflection.
One alternative is to define an AnimalFactory interface separate from the Animal class:
public interface AnimalFactory {
Animal getInstance(byte[] b);
}
public class DogFactory implements AnimalFactory {
public Dog getInstance(byte[] b) {
return new Dog(...);
}
}
public interface Animal {
// ...
}
class Dog implements Animal {
// ...
}