Abstract static factory method [getInstance()] in Java? - java

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 {
// ...
}

Related

Abstract class or casting?

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.

Conditionally instantiate a different class

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.

Static abstract method workaround

I would like to create a abstract static method in an abstract class. I am well aware from this question that this is not possible in Java. What is the default workaround / alternative way of thinking of the problem / is there an option for doing this for seemingly valid examples (Like the one below)?
Animal class and subclasses:
I have a base Animal class with various subclasses. I want to force all subclasses to be able to create an object from an xml string. For this, it makes no sense for anything but static does it? E.g:
public void myMainFunction() {
ArrayList<Animal> animals = new ArrayList<Animal>();
animals.add(Bird.createFromXML(birdXML));
animals.add(Dog.createFromXML(dogXML));
}
public abstract class Animal {
/**
* Every animal subclass must be able to be created from XML when required
* (E.g. if there is a tag <bird></bird>, bird would call its 'createFromXML' method
*/
public abstract static Animal createFromXML(String XML);
}
public class Bird extends Animal {
#Override
public static Bird createFromXML(String XML) {
// Implementation of how a bird is created with XML
}
}
public class Dog extends Animal {
#Override
public static Dog createFromXML(String XML) {
// Implementation of how a dog is created with XML
}
}
So in cases where I need a static method, and I need a way of forcing all subclasses to have an implementation of this static method, is there a way I can do that?
You can create a Factory to produce the animal objects, Below is a sample to give you a start:
public void myMainFunction() {
ArrayList<Animal> animals = new ArrayList<Animal>();
animals.add(AnimalFactory.createAnimal(Bird.class,birdXML));
animals.add(AnimalFactory.createAnimal(Dog.class,dogXML));
}
public abstract class Animal {
/**
* Every animal subclass must be able to be created from XML when required
* (E.g. if there is a tag <bird></bird>, bird would call its 'createFromXML' method
*/
public abstract Animal createFromXML(String XML);
}
public class Bird extends Animal {
#Override
public Bird createFromXML(String XML) {
// Implementation of how a bird is created with XML
}
}
public class Dog extends Animal {
#Override
public Dog createFromXML(String XML) {
// Implementation of how a dog is created with XML
}
}
public class AnimalFactory{
public static <T extends Animal> Animal createAnimal(Class<T> animalClass, String xml) {
// Here check class and create instance appropriately and call createFromXml
// and return the cat or dog
}
}

Overriding a method(with the same signature) present in both Parent Class as well as the Interface

We have a Class(say Animal), and we have an Interface(say Behave). Both Animal as well as Behave have a method with the same signature(say public void eat()).
When we try to write the body for the method eat() in a Class(say Dog) which extends Animal and implements Behave, which eat() method is actually referred to? The one in Animal or Behave. In whichever case that happens, why does it happen that way?
Edit:
I tried this scenario on Eclipse before posting this question.
An interesting part here is, even though I am implementing Behave, if I dont create an eat() method(i.e. if I dont implement Behave's inherited abstract method) inside Dog, there is no error, since I am already extending from Animal which has an eat() method.
which eat() method is actually referred to? BOTH.
Try this: if you don't override the method at all, when you call with the interface, you will get the one from the parent.
Behave b = new Dog();
System.out.println(b.eat());//this will call eat from Animal if Dog did not override.
If you override, you always get the one from the child:
Behavior b = new Dog();
Animal a = new Dog();
a.eat() and b.eat() will both refer to the eat inside of Dog class.
USE THESE CLASSES:
public class BClass {
public int add(int a, int b){
return a*b;
}
}
public interface BInterface {
public int add(int a, int b);
}
public class BChild extends BClass implements BInterface{
public static void main(String... args){
BInterface bi = new BChild();
BClass bc = new BChild();
System.out.println(bi.add(3, 5));
System.out.println(bi.add(3, 5));
}
#Override
public int add(int a, int b){
return a+b;
}
}
interface can contain only body definition of method , once you implements, it must have implementation of all defined methods. In you example
class Dog extends Animal implements Behave
{
#Override
public void eat() {...}
}
abstract class Animal{
public abstract void eat();
}
interface Behave{
void eat();
}
Here it need a body of abstract method where as it is in Main method. In other way
class DOG extends Animal implements Behave{
...
}
class Animal{
public void eat(){
...
}
}
interface Behave{
void eat();
}
Here Dog class having eat method body in its super class Animal. So it wount ask to implement body again in Animal as it is already implemented.
An interface simply defines a method that a class must provide. If we have
public class Animal{
public void eat(){
System.out.println("Om nom nom");
}
}
public class Dog extends Animal{
}
Dog now provides the eat method and can so implement Behave.
There is only one eat() method, because the designers of the language decided that the simplicity of having the method signature consist of its name and argument types was more useful than having the complexity of being able to specify that you are providing an implementation of an interface.
In Java, if the two have different semantics, provide a method which returns a Behave instance which does something else:
class Animal {
public void eat () { }
}
interface Behave {
void eat ();
}
class Dog extends Animal {
public void eat () {
// override of Animal.eat()
}
public Behave getBehave() {
return new Behave {
public void eat() {
BehaveEat();
}
};
}
private void BehaveEat() {
// effectively the implementation Behave.eat()
}
}
In other languages, you can explicitly state that a method implements a method from an interface.

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