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
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:
In my project I have a superclass and two subclasses extending from it. There is a method in the superclass that is overriden differently in each subclass.
I want to know if it's possible to introduce a method (in another class) that takes object of either subclass as a parameter and calls a method overriden in one of subclasses (depending on to which subclass does the object belong).
public class Superclass{
public int method(){return 0;}
}
public class Subclass1 extends Superclass{
public int method(){return 1;}
}
public class Subclass2 extends Superclass{
public int method(){return 2;}
}
public class CallingClass{
public static int dependantCall(Superclass parameter){return parameter.method}
I want to be able to do something like
Subclass1 subclassObject = new Subclass1;
System.out.println(CallingClass.dependantCall(subclassObject));
and get output
1
That is what Polymorphism is for! Defining the Superclass as a parameter type will allow you to pass either subclass in.
For example in your other class you can define it like this:
// classes Dog and Cat extend Animal and override makeNoise()
class Owner{
playWith(Animal a){
a.makeNoise();
}
}
Now the Owner can accept owner.makeNoise(cat) and owner.makeNoise(dog)
More reading: https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html
Yes, it is entirely possible. Here's how that method would look like:
public <T extends Superclass> void foo(T subclassObject) {
...
}
Or:
public void foo(Superclass obj) {
...
}
Note that in the above method, you can pass subclasses' objects as well (they are covariant data types).
This is what Java does by default when you create subclases, so no need to do anything special. Each object carries it's type information at run time, and the method invoked would always be the most specific one for the object. Example:
public class Doer {
public void doSomething() {
// Body presence
};
}
public class Painter extends Doer {
#Override
public void doSomething() {
// Paint here
}
}
public class Manager extends Doer {
#Override
public void doSomething() {
// Micromanage here
}
}
// Elsewhere in your code:
public void busyness(Doer doer) {
doer.doSomething();
}
A style note: if it is possible, one should prefer using interfaces instead of base classes (base classes those should be used only if you want to share implementation between subclasses). Example with interfaces:
public interface Doer {
void doSomething();
}
public class JackOfAllTrades implements Does {
#Override
public void doSomething() {
// Do whatever necessary
}
}
// Client code stays exactly the same as above:
public void busyness(Doer doer) {
doer.doSomething();
}
Note that in Java a class can have only one base class but can implement multiple interfaces.
#Override annotations are not strictly required, but they help Java compiler to spot some errors for you (e.g. if you misprint method name).
In your example it would look like
public class CallingClass {
public static int dependantCall(Superclass parameter) {
return parameter.method();
}
}
Subclass1 subclassObject = new Subclass1();
System.out.println(CallingClass.dependantCall(subclassObject));
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.
For my Java class, we are learning about interfaces, polymorphism, inheritance, etc.
The homework assignment I am working on is a memory game where you have pairs of cards all face down and you turn over two at a time looking for a match. If they match, they stay visible, if they don't, the cards are turned back over and you pick two more cards.
My design so far is as follows:
public interface Hideable
public abstract void hide();
public abstract void show();
public interface Speakable
public abstract String speak();
public interface AnimalCard extends Hideable, Speakable
public abstract boolean equals(Object obj);
public class Animal implements AnimalCard
public void hide() { ... }
public void show() { ... }
public boolean equals(Object obj) { ... }
// What do I do for the speak method since a generic Animal
// can't speak, but I have to provide a definition since the
// Animal class is implementing the interfaces.
public class Puppy extends Animal
// Here is where I need to define the speak method.
public String speak() { ... }
My question is in the comments above. I feel like I'm implementing this incorrectly with regard to the speak() method.
Just make the Animal class abstract.
Concrete classes will have to implement speak(), or be abstract themselves.
public class abstract Animal implements AnimalCard {
public void hide() { ... }
public void show() { ... }
public boolean equals(Object obj) { ... }
There's no need or value in declaring an abstract method for speak() in Animal - that method is implied by the class hierarchy.
the purpose of an interface is to guarantee that your class will behave in a certain way.
So if you declare a speakable object
Speakable speakingThing = new Puppy();
Whatever you put in that speakableThing variable must be able to do anything that the Speakable interfaces says it can do.
What I'd do, is not have AnimalCard implement Speakable and have only Animals that can speak implement the interface
Or, as other people said, if All your animals will speak, and you just will never instantiate the generic animal, than make your classes abstract.(abstract classes don't get instantiated. they're only there to be inherited from. )
you could make this kind of change
public abstract class Animal implements AnimalCard{
public void hide() { }
public void show() { }
public abstract String speak();
}
First,
you cant have abstract methods in an interface. They are essentially abstract by default, since it is illegal to have any implementation code within the interface.
Second, java doesnt support multiple inheritance, so your line:
public interface AnimalCard extends Hideable, Speakable
is illegal.
The best way to solve your problem once you fix those things is to make Animal card abstract.
public abstract Animal extends AnimalCard {
public void hide() { ... }
public void show() { ... }
public boolean equals(Object obj) { ... }
public abstract String speak();
}
public class Puppy extends Animal {
// Here is where I need to define the speak method.
public String speak() { ... }
}