Well, this is kind of embarrassing, but I've forgotten how to do the following in plain old Java:
abstract class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
}
class Flea extends Animal {
private double jumpHeight;
public Flea(String name, double jumpHeight) {
super(name);
this.jumpHeight = jumpHeight;
}
public double jump() {
return jumpHeight();
}
}
class Giraffe extends Animal {
private int strideLength;
public Giraffe(int strideLength) {
super("Berta");
this.strideLength = strideLength;
}
public int stride() { return strideLength; }
}
class Gorilla extends Animal {
private String call;
public Gorilla(String call) {
super("Boris");
this.call = call;
}
public String call() { return "Gorilla says " + call; }
}
Now I would like to decide the appropriate method at runtime, without having to add all the methods to each Animal (no abstract methods) and without meaningless placeholders (like imagine a Flea has no call).
I would like to do this without casting. So no:
if(Animal instanceof Gorilla) ((Gorilla) animal).call();
I could come up with a solution incorporating interfaces like jumpable and could use that, but I'm sure there was a certain pattern that was exactly for this kind of task.
Any ideas?
You should consider the visitor pattern:
abstract class Animal {
public abstract void acceptAnimalVisitor(AnimalVisitor visitor);
}
class Flea extends Animal {
public void acceptAnimalVisitor(AnimalVisitor visitor){
visitor.visit(this);
}
}
// other animals also implementing acceptAnimalVisitor
public class AnimalVisitor{
public void visit(Flea flea){
// ...
}
// other visit methods for the other animals
}
However, this requires at least one method (the accept method itself). Also note that you can convert the AnimalVisitor into an interface, and that way you can easily achieve the so called double dispatch.
Related
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 have a parent class:
public class Animal {
public Animal(String name, AnimalTypeEnum type) {
}
}
I have lots (in the case that has caused me to make this over 30) children:
public class Dog extends Animal {
public Dog(String name, AnimalTypeEnum type) {
super(name,type);
}
}
public class Cat extends Animal {
public Cat(String name, AnimalTypeEnum type) {
super(name,type);
}
}
The objects are constructed from many different places in the project (loaded on start up, created at various times in runtime. To "create" an object, I currently use this function (over 30 subclasses in the project, not just 2):
public static Animal create(String name, AnimalTypeEnum type) {
switch(type) {
case DOG:
return new Dog(name, type);
case CAT:
return new Cat(name, type);
}
}
It is important to note that none of the subclasses have any difference in parameters. The reason I'm using subclasses is because they have one or two functions that are overriden.
Say I now wanted to add a parameter for all subclasses, I'd need to:
Add the parameter to the Animal constructor
Add the parameter to the subclass constructors
Add the parameter to the create() function
(also change the parameter wherever the create() function is being called)
Ideally, I'd like to eliminate changing the subclass parameters (none of the subclasses have different parameters) and the create() function from the above process. But if that isn't possible, I'd like to find a better alternative to the create() function. The best solution I've thought of (psuedocode) is:
public Animal(String name, AnimalTypeEnum type) {
if (type == CAT) this.subclass(Cat);
if (type == DOG) this.subclass(Dog);
}
I think the above goes against the principle of class inheritance so I want to be clear that this isn't the solution I am trying to find, just how I imagine a solution could work.
This is a rather trivial issue but I feel that bad programming practices are behind it and I would like to rectify these. My questions would be (incase I haven't properly explained my problem/reasons):
Is inheritance even the ideal way to do this?
Is it possible to eliminate the process of changing the constructor in subclasses in this situation?
Is there anything I can do to remove the create() function, and assign the subclass when constructing Animal?
Thank you.
I think that you wonna use the Factory Pattern, so you have any options for solve your problem #Doleron showed the first one, but you can use this too:
public interface Animal {
public String getName();
}
The implementation Dog
public class Dog implements Animal{
private String name;
public Dog(String name) {
this.name=name;
}
#Override
public String getName() {
return name;
}
}
Cat
public class Cat implements Animal{
private String name;
public Cat(String name) {
this.name=name;
}
#Override
public String getName() {
return name;
}
}
Factory
public class AnimalFactory {
/*
* Some people use static attributs like:
* public static final String DOG ="DOG";
*/
public static Animal creatAnimal(String animal, String name){
if("DOG".equalsIgnoreCase(animal)){
return new Dog(name);
} else if("CAT".equalsIgnoreCase(animal)){
return new Cat(name);
}
return null;
}
}
Main
public static void main(String[] args) {
Animal animal = AnimalFactory.creatAnimal("dog", "pluto");
/*
* if you use static attribut you can call this form
*/
//Animal dog = AnimalFactory.creatAnimal(AnimalFactory.DOG, "pluto");
System.out.println("Name "+animal.getName()+ " class "+animal.getClass().getSimpleName() );
animal = AnimalFactory.creatAnimal("cat", "garfield");
System.out.println("Name "+animal.getName()+ " class "+animal.getClass().getSimpleName() );
}
you can see another example here.
Since you have an enum to identify the instance type, you could avoid the create/switch/if-else approach using a polymorphic enumeration like:
public enum AnimalTypeEnum {
CAT {
public Animal create(String name) {
return new Cat(name);
}
},
DOG {
public Animal create(String name) {
return new Dog(name);
}
},
COW {
public Animal create(String name) {
return new Cow(name);
}
};
abstract Animal create(String name);
}
As everything this approach has pros and cons. Please see if it fits to your requirements.
First of all, the base class Animal should be an abstract class, because you'll never give life to an Animal object but to a more specific type of Animal, i.e Dog, Cat et cetera. In this way, all animals will have some base methods already implemented.However, if some subclass needs to inherit from another class, you should consider Animal as an Interface, because Java doesn't allow multiple inheritance.
For your second question, if I correctly understand, why can't you add a protected member to the base class Animal and initialize it in the Animal costructor? Eventually, if subclasses as a specific value for this parameter, you can set it in the subclasses costructors.
Finally for the create() function in my opinion you should consider the Abstract Factory pattern.
I am exploring using the Builder design pattern to create subclasses of a parent object, based specifically on the generic type of the subclass. That sentence is kind of confusing, here is what I mean:
public class Animal(){
private String name;
private String gender;
public Animal(Builder<?> builder){
this.name = builder.name;
this.gender = builder.gender;
}
public static Builder<T extends Animal>{
private String name;
private String gender;
public Builder<T> setName(String name){
this.name = name;
return this;
}
public Builder<T> setGender(String gender){
this.gender = gender;
return this;
}
public T build(Class<T> clazz){
try {
Constructor<T> c = clazz.getDeclaredConstructor(Builder.class);
c.setAccessible(true);
return c.newInstance(this);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
}
Except, this ends up being rather error prone and "hackish". I want to be able to have one Builder that creates all the subclasses.
Question
Is there a better way to do this? Maybe the Builder design pattern is just not suited for my needs. This works, but doesn't feel right.
NOTE: The true needs of this question are not as trivial as the Animal class example. You could imagine I am trying to build a subclass to a parent class that contains many arguments. Using the builder pattern will make this a much easier instantiation and easier to extend for future subclasses.
The subclassed objects will have their own methods ONLY. No extra fields, only methods strictly defined to their type of subclass.
I.e. a Duck is a subclass of bird and it quacks. An emu is a subclass of bird, but I don't want it to quack, it will only run. But I both want them to have a name and gender.
Rather than the user specifying the Animal class, I would have each Animal subclass have its own Builder which can build that Animal.
That is:
public abstract class Animal {
protected Animal(Builder<?> builder) { ... }
public abstract static class Builder<T extends Animal> {
// setters for fields common to all animals go here
public abstract T build();
}
}
public final class Dog extends Animal {
private Dog(Builder builder) {
super(builder);
}
public static final class Builder extends Animal.Builder<Dog> {
#Override
public Dog build() {
return new Dog(this);
}
}
}
I have this abstract base class and each of it's childs should have a specific mandatory function but slightly different. Is this possible using the abstract class or should I be using an interface for this?
I will be using the structure like this
public abstract class Animal
{
//Mandatory method
Public void sound()
{
}
}
public class Cat extends Animal
{
public void sound()
{
System.out.println("Miauw");
}
}
public class Dog extends Animal
{
public void sound()
{
System.out.println("Woof");
}
}
//I will put all these child objects in a List<Animal> and need to call these methods.
for (Animal a : animalList)
{
a.sound();
}
How would one go about this structure? I have to add that I am using an abstract class because there are plenty of identical methods that need to be shared among the child classes. Just some of the methods need to be different from each other but mandatory and accessible from the base class.
You are looking for:
public abstract class Animal
{
//Mandatory method
abstract public void sound();
}
But also look at other users advices:
use lowercase for method names
the keyword publicalways goes in lowercase
use interfaces if your Animal class hasn't common code for all children classes
Both an abstract class and an interface would work in this case. The times when you'd want to use an abstract class is when there are common methods and data that you want shared among all subclasses. Such as, if Animal had a weight variable, and each subclass sets that variable.
NOTE: In an abstract class, any methods that you don't want to implement, you must declare as abstract. See how I modified Sound() below. Also, a bonus tip is that the standards say that method names should start with a lowercase letter, so I changed Sound to sound.
public abstract class Animal
{
private int weight;
public void setWeight(int weight) {
this.weight = weight;
}
public int getWeight() {
return weight;
}
//Mandatory method
abstract public void sound();
}
public class Cat extends Animal
{
public Cat(int weight) {
this.setWeight(weight);
}
public void sound()
{
System.out.println("Miauw");
}
}
public class Dog extends Animal
{
public Dog(int weight) {
this.setWeight(weight);
}
public void sound()
{
System.out.println("Woof");
}
}
You are looking for Java's abstract modifier. The official Java Documentation contains more specific information about abstract and final here.
public abstract class Animal
{
// Mandatory method with no "default" implementation.
public abstract void Sound();
// Optional method with a default implementation.
public void Move() {
// some actions here
}
// Optional method with a fixed implementation (it can't be changed in a child class).
public final void Eat(Food food) {
// some actions here
}
}
you should use interface in this case because you are not defining any method, if you only want to provide declaration interface is ok for that
if you use abstract class you overhead by overriding the method and define it again
Is there a point to using interface types in implementations, or should you only use them as part of the public interface of a class or interface?
Example (Java):
public class SomeClass {
// Declare list as..
private List<Object> list = new ArrayList<Object>();
// or...
private ArrayList<Object> list = new ArrayList<Object>();
// Does it matter which way list is declared if it's part
// of the private implementation?
// This parameter should be the most general interface type
// allowed because it's public-facing.
public void someMethod(List<Object> list) {
// ...
}
}
By defining them as abstract as possible, you're hiding implementation details. Should you ever wish to use a different subclass from List<T> instead of ArrayList<T>, then you can do so without breaking code everywhere.
Always make it as abstract as possible while still having the methods available that you need. That way your implementation is as flexible as possible.
For example, I am a person with a pet. Right now I have a cat, but what if I get on a vacation to Africa and happen to see a very awesome elephant? My cat will starve because nobody gave her food and I will put the elephant in my pocket back to Belgium. If I were to define it as a cat, I would have to change my entire class. Instead, I define it as an animal.
public class Person {
String name;
Animal pet;
// Getters & Setters + Constructor
}
public abstract class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class Cat extends Animal {
public Cat() { super("Cat")); }
}
public class Elephant extends Animal {
public Elephant() { super("Elephant")); }
}
public class Lion extends Animal {
public Lion() { super("Lion")); }
}
So when I make a new Person:
Person bestPersonInTheWorld = new Person();
bestPersonInTheWorld.setName("Jeroen");
bestPersonInTheWorld.setPet(new Cat());
I can simply kill the cat
bestPersonInTheWorld.dontFeedForTwoWeeks();
And I put my Elephant in the yard:
bestPersonInTheWorld.setPet(new Elephant());
Nothing has to be changed when it comes to implementation.