This question has been asked in a C++ context but I'm curious about Java. The concerns about virtual methods don't apply (I think), but if you have this situation:
abstract class Pet
{
private String name;
public Pet setName(String name) { this.name = name; return this; }
}
class Cat extends Pet
{
public Cat catchMice() {
System.out.println("I caught a mouse!");
return this;
}
}
class Dog extends Pet
{
public Dog catchFrisbee() {
System.out.println("I caught a frisbee!");
return this;
}
}
class Bird extends Pet
{
public Bird layEgg() {
...
return this;
}
}
{
Cat c = new Cat();
c.setName("Morris").catchMice(); // error! setName returns Pet, not Cat
Dog d = new Dog();
d.setName("Snoopy").catchFrisbee(); // error! setName returns Pet, not Dog
Bird b = new Bird();
b.setName("Tweety").layEgg(); // error! setName returns Pet, not Bird
}
In this sort of class hierarchy, is there any way to return this in a way that doesn't (effectively) upcast the the object type?
If you want to avoid unchecked cast warnings from your compiler (and don't want to #SuppressWarnings("unchecked")), then you need to do a little more:
First of all, your definition of Pet must be self-referential, because Pet is always a generic type:
abstract class Pet <T extends Pet<T>>
Secondly, the (T) this cast in setName is also unchecked. To avoid this, use the "getThis" technique in the excellent Generics FAQ by Angelika Langer:
The "getThis" trick provides a way to
recover the exact type of the this
reference.
This results in the code below, which compiles and runs without warnings. If you want to extend your subclasses, then the technique still holds (though you'll probably need to genericise your intermediate classes).
The resulting code is:
public class TestClass {
static abstract class Pet <T extends Pet<T>> {
private String name;
protected abstract T getThis();
public T setName(String name) {
this.name = name;
return getThis(); }
}
static class Cat extends Pet<Cat> {
#Override protected Cat getThis() { return this; }
public Cat catchMice() {
System.out.println("I caught a mouse!");
return getThis();
}
}
static class Dog extends Pet<Dog> {
#Override protected Dog getThis() { return this; }
public Dog catchFrisbee() {
System.out.println("I caught a frisbee!");
return getThis();
}
}
public static void main(String[] args) {
Cat c = new Cat();
c.setName("Morris").catchMice();
Dog d = new Dog();
d.setName("Snoopy").catchFrisbee();
}
}
How about this old trick:
abstract class Pet<T extends Pet>
{
private String name;
public T setName(String name) { this.name = name; return (T) this; }
}
class Cat extends Pet<Cat>
{
/* ... */
}
class Dog extends Pet<Dog>
{
/* ... */
}
No, not really. You could work around it by using covariant return types (thanks to McDowell for the correct name):
#Override
public Cat setName(String name) {
super.setName(name);
return this;
}
(Covariant return types are only in Java 5 and above, if that's a concern for you.)
It's a bit convoluted, but you can do this with generics:
abstract class Pet< T extends Pet > {
private String name;
public T setName( String name ) {
this.name = name;
return (T)this;
}
public static class Cat extends Pet< Cat > {
public Cat catchMice() {
System.out.println( "I caught a mouse!" );
return this;
}
}
public static class Dog extends Pet< Dog > {
public Dog catchFrisbee() {
System.out.println( "I caught a frisbee!" );
return this;
}
}
public static void main (String[] args){
Cat c = new Cat();
c.setName( "Morris" ).catchMice(); // error! setName returns Pet, not Cat
Dog d = new Dog();
d.setName( "Snoopy" ).catchFrisbee(); // error! setName returns Pet, not Dog
}
}
public class Pet<AnimalType extends Pet> {
private String name;
public AnimalType setName(String name) {
this.name = name; return (AnimalType)this;
}
}
and
public class Cat extends Pet<Cat> {
public Cat catchMice() {return this;}
public static void main(String[] args) {
Cat c = new Cat().setName("bob").catchMice();
}
}
Related
So the compiler complains when ever i do a explicit cast. I can prevent this by using a #SuppressWarnings annotation.
At this point i would have this annotation a lot in my code which lets me suspect that there is another way i'm just not aware of.
Lets have a look at this example
class CutePet
{
public void pet()
{
System.out.println( "The cute pet gets some pets" );
}
}
class Cat extends CutePet
{
public void letOutside()
{
System.out.println( "The cat goes outside" );
}
public void letInside()
{
System.out.println( "The cat comes inside" );
}
public void removeTick()
{
System.out.println( "The cat looses all ticks" );
}
}
class Dog extends CutePet
{
public void goForAWalk()
{
System.out.println( "The Dog goes for a walk" );
}
public void tellHimWhatHeIs()
{
System.out.println( "The Dog is a good boy" );
}
}
class caretaker
{
public void takeCare( CutePet pet )
{
if( pet instanceof Cat )
{
pet.pet();
((Cat)pet).letOutside();
((Cat)pet).letInside();
((Cat)pet).removeTick();
}
else if( pet instanceof Dog )
{
pet.pet();
((Dog)pet).goForAWalk();
((Dog)pet).tellHimWhatHeIs();
}
}
}
The Caretaker does not know what kind of Pet he will get in advance and he my has several pets of different kinds.
I tried to give the Cute pet class a getType() method which returns a enum. With this enum i can remove the "instanceof" but the cast is still there.
Am i missing something?
If this were a real world problem, the caretaker would recognize which kind of pet he has based on the pet's appearance. While "instance of" is one way of looking at it, you might want to consider overloading the takeCare method directly with the subtypes as required. For example:
class Caretaker {
public void takeCare(Cat pet) {
pet.pet();
pet.letOutside();
pet.letInside();
pet.removeTick();
}
public void takeCare(Dog pet) {
pet.pet();
pet.goForAWalk();
pet.tellHimWhatHeIs();
}
}
in other words, the caretaker knows what to do (has methods already in place) for the kind of pet he receives.
EDIT
In response to some of the comments, yes, the original example shifts the problem further up. If you have an array or a list of generic pets then you still have to figure out what kinds of pets you have to give them to the caretaker. Conceptually it seems strange that the pet should be able to pet itself, take itself for a walk, etc. (these methods are part of the pet class when it should be the caretaker doing these actions ON the pet).
I've since rewritten the code with a full working example below with a Job class that has a perform method. This method will return the appropriate job based on the type of animal the caretaker has. The caretaker can then perform the job on the pet in question. See below.
Doing things this way avoids instanceof. While it is debatable how good/bad instanceof actually is, where possible it should be the object itself to tell me what it needs, otherwise the whole polymorphism concept can get pretty hairy pretty quick.
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
Caretaker caretaker = new Caretaker();
Arrays.asList(
new Cat("Cat1"),
new Cat("Cat2"),
new Dog("Dog1")
).forEach(caretaker::takeCare);
}
interface CutePet {
String whoAmI();
Job whatINeed();
}
abstract static class NamedCutePet implements CutePet {
private final String name;
public NamedCutePet(String name) {
this.name = name;
}
public String whoAmI() {
return this.name;
}
}
static class Cat extends NamedCutePet {
public Cat(String name) {
super(name);
}
#Override
public Job whatINeed() {
return new CatJob(this);
}
}
static class Dog extends NamedCutePet {
public Dog(String name) {
super(name);
}
#Override
public Job whatINeed() {
return new DogJob(this);
}
}
static class Caretaker {
void takeCare(CutePet pet) {
pet.whatINeed().perform();
}
}
static abstract class BaseJob implements Job {
void pet(CutePet pet) {
System.out.println(String.format("The cute pet %s gets some pets", pet.whoAmI()));
}
}
static class DogJob extends BaseJob {
private final Dog dog;
public DogJob(Dog dog) {
this.dog = dog;
}
#Override
public void perform() {
pet(dog);
takeDogFarAWalk(dog);
tellHimWhatHeIs(dog);
}
private void takeDogFarAWalk(Dog dog) {
System.out.println(String.format("The dog %s goes for a walk", dog.whoAmI()));
}
private void tellHimWhatHeIs(Dog dog) {
System.out.println(String.format("The dog %s is a good boy", dog.whoAmI()));
}
}
static class CatJob extends BaseJob {
private final Cat cat;
public CatJob(Cat cat) {
this.cat = cat;
}
#Override
public void perform() {
pet(cat);
letOutside(cat);
letInside(cat);
removeTick(cat);
}
private void letOutside(Cat cat) {
System.out.println(String.format("The cat %s goes outside", cat.whoAmI()));
}
private void letInside(Cat cat) {
System.out.println(String.format("The cat %s comes inside", cat.whoAmI()));
}
private void removeTick(Cat cat) {
System.out.println(String.format("The cat %s loses all ticks", cat.whoAmI()));
}
}
interface Job {
void perform();
}
}
Let's make it clear: you can't call subclass specific methods without typecasting to subclass type.
Now, let me suggest an alternate way. Define a method takeCare() in the superclass and let the subclasses implement it by calling several specific methods specific to subclasses. Then from CareTaker#takeCare(), call only takeCare() method without typecasting.
Several other alternate approaches can be used to solve the situation.
Here is how you would do it with interfaces and reflection. Note that only the interface methods are called for each pet type. It could also be extended to call other methods.
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class PetProblem {
public static void main(String[] args) {
Caretaker caretaker = new Caretaker();
Dog dog = new Dog();
caretaker.takeCare(dog);
System.out.println("\nNow do it for the cat\n");
Cat cat = new Cat();
caretaker.takeCare(cat);
}
}
interface CuteCat {
void letOutside();
void letInside();
void removeTick();
}
interface CuteDog {
void goForAWalk();
void tellHimWhatHeIs();
}
interface CutePet {
default void pet() {
System.out.println("The cute pet gets some pets");
}
}
class Cat implements CutePet, CuteCat {
public void letOutside() {
System.out.println("The cat goes outside");
}
public void letInside() {
System.out.println("The cat comes inside");
}
public void removeTick() {
System.out.println("The cat looses all ticks");
}
}
class Dog implements CutePet, CuteDog {
public void goForAWalk() {
System.out.println("The Dog goes for a walk");
}
public void tellHimWhatHeIs() {
System.out.println("The Dog is a good boy");
}
}
class Caretaker {
public void takeCare(Object pet) {
Class<?>[] ifss = pet.getClass().getInterfaces();
for (Class<?> ifs : ifss) {
Method[] methods = ifs.getDeclaredMethods();
for (Method m : methods) {
try {
m.invoke(pet);
}
catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
Note however, that using interfaces and having a method so named that it can be used for all pets is easier. Here is an example. Since both dogs and cats need to eat, a common method feedMe() can be implemented for each.
public class AnimalShelter {
public static void main(String[] args) {
Caretaker caretaker = new Caretaker();
Dog dog = new Dog();
Cat cat = new Cat();
caretaker.feedThePets(dog);
caretaker.feedThePets(cat);
}
}
interface SupperTime {
void feedMe();
}
class Caretaker {
public void feedThePets(SupperTime pet) {
pet.feedMe();
}
}
class Dog implements SupperTime {
public void feedMe() {
System.out.println("Oh boy, Kibbles n' Bits");
}
}
class Cat implements SupperTime {
public void feedMe() {
System.out.println("Yum. Purina Cat Chow");
}
}
Question is related to classes below. Zookeeper1 and Zookeeper2 are 2 alternatives that I could use. I can potentially store in future different types of animals inside Zookeeper. I should be able to get those classes. In 1st case I store all animals in list (meaning in future I can add other new Animals easily), but I need to cast dog with (Dog) when I need to get it. Read somewhere that casts are code-smell, so I wanted to see if there are any alternatives? Other solution prevents casting, but has problem of adding new lists each time I add new animal.
class AnimalId{}
interface Animal{
AnimalId getAnimalId();
void breathe();
}
class Cat implements Animal{
public AnimalId getAnimalId() { return null; }
public void breathe() {}
}
class Dog implements Animal{
public AnimalId getAnimalId() { return null; }
public void breathe() {}
public void bark(){}
}
class ZooKeeper1{
Map<AnimalId, Animal> animals = new HashMap<>(); //future-proof
void addAnimal(Animal a){
animals.put(a.getAnimalId(), a);
}
void printAnimals(){
animals.forEach((key, value) -> System.out.println(key));
}
Dog getDog(AnimalId animalId){
return (Dog)animals.get(animalId); //NOK - must type-cast!
}
public static void main(String[] args) {
ZooKeeper1 zk1 = new ZooKeeper1();
zk1.addAnimal(new Cat());
zk1.addAnimal(new Dog());
zk1.printAnimals();
Dog d = zk1.getDog(new AnimalId());
d.bark();
}
}
class ZooKeeper2{
Map<AnimalId, Cat> cats = new HashMap<>();
Map<AnimalId, Dog> dogs = new HashMap<>(); //will need to add more lines in future
void addCat(Cat c){
cats.put(c.getAnimalId(), c);
}
void addDog(Dog d){
dogs.put(d.getAnimalId(), d); //will need to add more lines in future
}
void printAnimals(){
cats.forEach((key, value) -> System.out.println(key));
dogs.forEach((key, value) -> System.out.println(key)); //will need to add more lines in future
}
Dog getDog(AnimalId animalId){
return dogs.get(animalId); //OK no type-cast
}
public static void main(String[] args) {
ZooKeeper2 zk2 = new ZooKeeper2();
zk2.addCat(new Cat());
zk2.addDog(new Dog());
zk2.printAnimals();
Dog d = zk2.getDog(new AnimalId());
d.bark();
}
}
Imagine I wrote class ZooKeeper1 without any knowledge of class Dog and passed it on to you. You then decide to extend the class and add the method Dog getDog(AnimalId id).
Would you expect this to just work? If you see the gap in your reasoning, then you understand why casting is a bad idea.
Casting is a not a miracle solution. The only safe way to use it is to only cast objects of known types; for example, if you store a Dog instance in a variable of type Animal, then you know for sure that you can cast the result of getAnimal(..) to type Dog.
OK, so after looking into heterogeneous containers in Java, I guess this would be so far the best option I have? Any comments on this type of solution?
interface Animal { AnimalId getId(); }
class AnimalId { int id; AnimalId(int id){this.id = id;} public boolean equals(Object o){ return id==((AnimalId)o).id; } public int hashCode(){ return 1; } }
class Cat implements Animal { AnimalId id; Cat(AnimalId id){this.id=id;} public AnimalId getId(){ return id; } public String catSpecific(){ return "CS"; } }
class Dog implements Animal { AnimalId id; Dog(AnimalId id){this.id=id;} public AnimalId getId(){ return id; } public String dogSpecific(){ return "DS"; } }
class Zoo {
private Map<Class<? extends Animal>, Map<AnimalId, Animal>> animals = new HashMap<>();
public <T extends Animal> void assignAnimal(T animal){
animals.computeIfAbsent(animal.getClass(), k -> new HashMap<>()).put(animal.getId(), animal);
}
public <T extends Animal> T getAnimal(Class<T> type, AnimalId animalId){
return type.cast(animals.get(type).get(animalId));
}
public static void main(String[] args) {
Zoo zoo = new Zoo();
AnimalId animalId = new AnimalId(1);
Animal animal1 = new Cat(animalId);
Animal animal2 = new Dog(animalId);
zoo.assignAnimal(animal1);
zoo.assignAnimal(animal2);
Cat cat = zoo.getAnimal(Cat.class, animalId);
Dog dog = zoo.getAnimal(Dog.class, animalId);
System.out.println(cat.catSpecific());
System.out.println(dog.dogSpecific());
}
}
This question already has answers here:
why java polymorphism not work in my example
(3 answers)
Closed 6 years ago.
I have a situation
public class Animal
{
String noise;
public String makeNoise()
{
return noise;
}
}
Then there will be a subclass with the concrete definition of the noise.
public class Dog extends Animal{
String noise = "woof";
}
also
public class Cat extends Animal{
String noise = "meow";
}
What I want to do is
Animal cat = new Cat();
cat.makeNoise(); // This will be 'meow'
and
Animal dog = new Dog();
dog.makeNoise(); // This will be 'woof'
Basically, I don't want to repeat the makeNoise() method when I create an animal. However, this will not work. (Noise is an empty string)
I could use a static object like
static String NoiseDog = "woof"
static String NoiseCat = "meow"
but then again I have to write the makeNoise() method for each animal. Is there a better way to architect this?
If you want to force all sub-classes of Animal to have a noise defined, you can enforce that in the constructor:
public abstract class Animal {
private final String noise;
public Animal(final String noise) {
this.noise = noise;
}
public String makeNoise() {
return noise;
}
}
Then Dog:
public class Dog extends Animal {
public Dog() {
super("woof");
}
}
And Cat:
public class Cat extends Animal {
public Cat() {
super("meow");
}
}
And to test it out:
public class Test {
public static void main(String[] args) {
final Animal dog = new Dog();
System.out.println(dog.makeNoise());
final Animal cat = new Cat();
System.out.println(cat.makeNoise());
}
}
Output:
woof
meow
public class Cat extends Animal{
String noise = "meow";
}
This creates an instance variable named "noise" that hides the superclass variable.
Instead, you need this to set the superclass value:
public class Cat extends Animal{
public Cat() {
noise = "meow";
}
}
Make the Animal class abstract. This way, there can be no such thing as an Animal object which calls makeNoise.
Then, set the noise String to a value within the constructor of each subclass as appropriate to that animal's sound.
Alternatively, you could implement an interface like so:
Animal:
public interface Animal {
public String makeNoise();
}
Dog:
public class Dog implements Animal {
public String makeNoise() {
return "woof";
}
}
Cat:
public class Cat implements Animal {
public String makeNoise() {
return "meow";
}
}
Test:
public class Test {
public static void main(String[] args) {
Animal dog = new Dog();
System.out.println(dog.makeNoise());
Animal cat = new Cat();
System.out.println(cat.makeNoise());
}
}
Output:
woof
meow
I'm doing a simple Zoo application to understand oriented object concepts in Java.
My model is as follow:
1) A Zoo has a number of Cages
2) A Cage has a a mixture of Feline, Primate or Bird
3) An Animal can eat, sleep or drink
4) Feline extends Animal (Do extra Feline stuff)
5) Primate extends Animal (Do extra Primate stuff)
6) Bird extends Animal (Do extra Bird stuff)
The problem:
While it's pretty easy to handle x number of cages in a zoo (ArrayList of Cage), I'm struggling with the Animals in Cage.
I found out that I need to have an ArrayList of Object.
So far so good, but when I try to obtain my animal back and have him scratch a post, it's not a Feline anymore, it's an Object.
public class Cage{
private String name;
private ArrayList<Object> animals = new ArrayList<Object>();
public Cage(String name){
this.name = name;
}
public void addFeline(String name){
Feline newFeline= new Feline(name);
this.animals.add(newFeline);
}
public void addPrimate(String name){
Primate newPrimate= new Primate(name);
this.animals.add(newPrimate);
}
public void addBird(String name){
Bird newBird= new Bird(name);
this.animals.add(newBird);
}
public void removeAnimal(int index){
this.animals.remove(index);
}
public Object getAnimal(int index){
Object myAnimal = this.animals.get(index);
return myAnimal;
}
}
And the way I call it:
Zoo myZoo = new Zoo("My Zoo");
myZoo.addCage("Monkey Exhibit");
Cage myCage = myZoo.getCage(0);
myCage.addFeline("Leo");
Object MyAnimal = myCage.getAnimal(0);
The Question: How can I turn Object back into instance of class Feline so it can Scratch a Post?
I think the best way to approach this problem would be using the Strategy design pattern.
Feline, Primate and Bird should implement an interface Animal. The Cage would then have a method public void addAnimal(Animal animal);
The object creation for Feline, Primate and Bird should be outside of Cage.
I have put together some code if this can help. I would design the application similar to something below.
Behaviours should be encapsulated using interfaces. e.g. EatingBehaviour
public interface Animal {
public String getName();
}
public interface EatingBehaviour {
public void howManyTimes();
}
public class RealLionEatingBehaviour implements EatingBehaviour{
#Override
public void howManyTimes() {
System.out.println("I eat once a day");
}
}
public class ToyLionEatingBehaviour implements EatingBehaviour {
#Override
public void howManyTimes() {
System.out.println("I never eat! I am a toy lion.");
}
}
public abstract class Feline implements Animal{
public abstract void scratchPost();
private EatingBehaviour eatingBehaviour;
public EatingBehaviour getEatingBehaviour() {
return eatingBehaviour;
}
public void setEatingBehaviour(EatingBehaviour eatingBehaviour) {
this.eatingBehaviour = eatingBehaviour;
}
}
public class Lion extends Feline {
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
Lion (String name) {
this.name=name;
}
public void scratchPost(){
System.out.println(getName() + " Lion Scratching Post!");
}
}
public class AnimalFactory {
public static Animal getAnimalInstance(String type, String name){
Animal animal=null;
if ("lion".equalsIgnoreCase(type)) {
animal = new Lion(name);
}
return animal;
}
}
import java.util.ArrayList;
import java.util.List;
public class Cage {
private List<Animal> animals = new ArrayList<Animal>();
public void addAnimal(Animal animal) {
animals.add(animal);
}
public void removeAnimal(int index){
this.animals.remove(index);
}
public Animal getAnimal(int index){
return this.animals.get(index);
}
}
public class Zoo {
public static void main(String args[]) {
Cage cage = new Cage();
Animal animal = null;
animal = AnimalFactory.getAnimalInstance("Lion", "Sweety");
cage.addAnimal(animal);
Animal animalFromCage = cage.getAnimal(0);
if (animalFromCage instanceof Feline) {
Feline feline = (Feline) animalFromCage;
feline.setEatingBehaviour(new RealLionEatingBehaviour());
feline.scratchPost();
feline.getEatingBehaviour().howManyTimes();
feline.setEatingBehaviour(new ToyLionEatingBehaviour());
feline.getEatingBehaviour().howManyTimes();
}
}
}
Use a cast:
Object myAnimal = myCage.getAnimal(0);
Feline f = (Feline) myAnimal;
private List<Animal> animals = new ArrayList<Animal>();
public void findAnimal(int index) {
Animal myAnimal = animals.get(index);
if (myAnimal instanceof Feline) {
Feline feline = (Feline) myAnimal;
//do the work with Feline
} else if (myAnimal instanceof Primate) {
//do the work with Primate
}
// continue with the other types.
}
this will avoid a unexpected classcast exception. Since you know the type use the super type (Animal) in the Arraylist instead fo Object. if it is Obejct you can add anything to the List.
You should use an ArrayList<? extends Animal> instead of ArrayList<Object>. You would then cast a return value to the appropriate subclass of Animal.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Suppose we had this class
Animal.java
public class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
public void shout() {
/* must be override */
}
public String getName() {
return name;
}
}
Driver.java
import java.util.ArrayList;
import java.util.List;
public class Driver {
public static void main(String[] args) {
List<Animal> animals = new ArrayList<Animal>();
animals.add(new Animal("Dog") {
#Override
public void shout() {
System.out.println(getName() + " sounds like: woof woof woof");
}
});
animals.add(new Animal("Cat") {
#Override
public void shout() {
System.out.println(getName() + " sounds like: meow meow meow-ow");
}
});
for(Animal a : animals)
a.shout();
}
}
how can i boost me to implement the method shout() or any other programmer? Suppose that there is no reason to make the Animal class abstract, and make a class for Dog,Cat, etc.. that extends Animal
Is there a design pattern?
mmm a Strategy pattern could help you.
public class Animal {
private Shoutable shoutable;
private String name;
public Animal(String name) {
this.name = name;
}
public void shout() {
shoutable.shout();
}
public String getName() {
return name;
}
public void setShout(Shoutable shoutable){
this.shoutable=shoutable;
}
}
public interface Shoutable{
void shout();
}
public class DogShout implements Shoutable{
#Override
public void shout{
System.out.println("woff gua guaa gua woff");
}
}
You could implement shout() in the base class and add method voice() that returns the voice of the animal.
Like this:
public class Animal {
private String voice;
private String name;
public Animal(String name, String voide) {
this.name = name;
this.voice = voice;
}
public void shout() {
System.out.println(getName() + " sounds like: "+ getVoice());
}
public String getName() {
return name;
}
public String getVoice() { return voice }
}
In the code that creates animals:
animals.add(new Animal("Dog", "woof"));
animals.add(new Animal("Cat", "meow");
If you want Cat and Dog to do the things that Animal does without animal being Abstract, you can.
public class Cat extends Animal
that will work if Animal is Abstract or a normal, fully implemented class. You would use implements instead of extends for an interface.
You can do the following:
public class Animal {
private String name;
private Shoutable shoutable;
public Animal(String name, Shoutable shoutable) {
this.name = name;
this.shoutable = shoutable;
}
public void shout() {
shoutable.shout();
}
public String getName() {
return name;
}
}
The Shoutable interface:
public interface Shoutable {
void shout();
}
And have a shoutable implementation as anonymous inner class:
import java.util.ArrayList;
import java.util.List;
public class Driver {
public static void main(String[] args) {
List<Animal> animals = new ArrayList<Animal>();
animals.add(new Animal("Dog", new Shoutable() {
#Override
public void shout() {
System.out.println(getName() + " sounds like: woof woof woof");
}
});
animals.add(new Animal("Cat", new Shoutable() {
#Override
public void shout() {
System.out.println(getName() + " sounds like: meow meow meow-ow");
}
});
for(Animal a : animals)
a.shout();
}
}