Skip to content

Animal Inheritance System with Advanced Features

Question

Design an object-oriented system in Java that implements an animal hierarchy with the following requirements: 1. Create an abstract class Animal with: - Abstract method makeSound() - Abstract method move() - Concrete method getAge() - Protected field for age 2. Create interfaces Pet and Wild with appropriate methods 3. Implement Dog, Cat, and Bird classes that extend Animal 4. Create Puppy and Kitten classes that extend Dog and Cat respectively 5. Use a Zoo class to manage animals using a Map<String, Animal> 6. Implement a Visitor pattern for animal interactions 7. Add support for animal training and tricks 8. Include proper exception handling and validation

Answer

Here's a implementation of the animal inheritance system:

Core Classes

  1. Animal Abstract Class

    public abstract class Animal {
        protected int age;
        protected String name;
        protected List<String> tricks;
    
        public Animal(String name, int age) {
            if (age < 0) {
                throw new IllegalArgumentException("Age cannot be negative");
            }
            if (name == null || name.trim().isEmpty()) {
                throw new IllegalArgumentException("Name cannot be null or empty");
            }
            this.name = name;
            this.age = age;
            this.tricks = new ArrayList<>();
        }
    
        public abstract String makeSound();
        public abstract void move();
    
        public int getAge() {
            return age;
        }
    
        public String getName() {
            return name;
        }
    
        public void addTrick(String trick) {
            if (trick == null || trick.trim().isEmpty()) {
                throw new IllegalArgumentException("Trick cannot be null or empty");
            }
            tricks.add(trick);
        }
    
        public List<String> getTricks() {
            return new ArrayList<>(tricks);
        }
    
        public void accept(AnimalVisitor visitor) {
            visitor.visit(this);
        }
    }
    

  2. Interfaces

    public interface Pet {
        void play();
        void feed();
        void groom();
    }
    
    public interface Wild {
        void hunt();
        void defend();
        void markTerritory();
    }
    

  3. Animal Classes

    public class Dog extends Animal implements Pet {
        private String breed;
    
        public Dog(String name, int age, String breed) {
            super(name, age);
            this.breed = breed;
        }
    
        @Override
        public String makeSound() {
            return "Woof!";
        }
    
        @Override
        public void move() {
            System.out.println(name + " runs on four legs");
        }
    
        @Override
        public void play() {
            System.out.println(name + " plays fetch");
        }
    
        @Override
        public void feed() {
            System.out.println(name + " eats dog food");
        }
    
        @Override
        public void groom() {
            System.out.println(name + " gets brushed");
        }
    
        public void fetch() {
            System.out.println(name + " fetches the ball");
        }
    }
    
    public class Cat extends Animal implements Pet {
        private boolean isIndoor;
    
        public Cat(String name, int age, boolean isIndoor) {
            super(name, age);
            this.isIndoor = isIndoor;
        }
    
        @Override
        public String makeSound() {
            return "Meow!";
        }
    
        @Override
        public void move() {
            System.out.println(name + " walks gracefully");
        }
    
        @Override
        public void play() {
            System.out.println(name + " plays with yarn");
        }
    
        @Override
        public void feed() {
            System.out.println(name + " eats cat food");
        }
    
        @Override
        public void groom() {
            System.out.println(name + " grooms itself");
        }
    
        public void climb() {
            System.out.println(name + " climbs the tree");
        }
    }
    
    public class Bird extends Animal implements Wild {
        private String species;
        private boolean canFly;
    
        public Bird(String name, int age, String species, boolean canFly) {
            super(name, age);
            this.species = species;
            this.canFly = canFly;
        }
    
        @Override
        public String makeSound() {
            return "Tweet!";
        }
    
        @Override
        public void move() {
            if (canFly) {
                System.out.println(name + " flies through the air");
            } else {
                System.out.println(name + " hops on the ground");
            }
        }
    
        @Override
        public void hunt() {
            System.out.println(name + " hunts for insects");
        }
    
        @Override
        public void defend() {
            System.out.println(name + " defends its nest");
        }
    
        @Override
        public void markTerritory() {
            System.out.println(name + " sings to mark territory");
        }
    
        public void buildNest() {
            System.out.println(name + " builds a nest");
        }
    }
    

  4. Subclasses

    public class Puppy extends Dog {
        private boolean isHouseTrained;
    
        public Puppy(String name, int age, String breed, boolean isHouseTrained) {
            super(name, age, breed);
            this.isHouseTrained = isHouseTrained;
        }
    
        @Override
        public String makeSound() {
            return "Yip!";
        }
    
        @Override
        public void move() {
            System.out.println(name + " runs and stumbles");
        }
    
        public void learnTrick(String trick) {
            addTrick(trick);
            System.out.println(name + " learned to " + trick);
        }
    }
    
    public class Kitten extends Cat {
        private boolean isLitterTrained;
    
        public Kitten(String name, int age, boolean isIndoor, boolean isLitterTrained) {
            super(name, age, isIndoor);
            this.isLitterTrained = isLitterTrained;
        }
    
        @Override
        public String makeSound() {
            return "Mew!";
        }
    
        @Override
        public void move() {
            System.out.println(name + " runs and pounces");
        }
    
        public void learnTrick(String trick) {
            addTrick(trick);
            System.out.println(name + " learned to " + trick);
        }
    }
    

Zoo Management

  1. Zoo Class
    public class Zoo {
        private final Map<String, Animal> animals;
    
        public Zoo() {
            this.animals = new HashMap<>();
        }
    
        public void addAnimal(Animal animal) {
            if (animal == null) {
                throw new IllegalArgumentException("Animal cannot be null");
            }
            if (animals.containsKey(animal.getName())) {
                throw new IllegalStateException("Animal with name " + 
                    animal.getName() + " already exists");
            }
            animals.put(animal.getName(), animal);
        }
    
        public Animal getAnimal(String name) {
            return animals.get(name);
        }
    
        public void removeAnimal(String name) {
            animals.remove(name);
        }
    
        public void makeAllAnimalsSound() {
            animals.values().forEach(animal -> 
                System.out.println(animal.getName() + ": " + animal.makeSound()));
        }
    
        public void trainAnimal(String name, String trick) {
            Animal animal = getAnimal(name);
            if (animal == null) {
                throw new IllegalArgumentException("Animal not found: " + name);
            }
            animal.addTrick(trick);
        }
    
        public List<Animal> getAnimalsByType(Class<? extends Animal> type) {
            return animals.values().stream()
                .filter(type::isInstance)
                .collect(Collectors.toList());
        }
    }
    

Visitor Pattern

  1. Animal Visitor
    public interface AnimalVisitor {
        void visit(Dog dog);
        void visit(Cat cat);
        void visit(Bird bird);
        void visit(Puppy puppy);
        void visit(Kitten kitten);
    }
    
    public class FeedingVisitor implements AnimalVisitor {
        @Override
        public void visit(Dog dog) {
            dog.feed();
        }
    
        @Override
        public void visit(Cat cat) {
            cat.feed();
        }
    
        @Override
        public void visit(Bird bird) {
            System.out.println(bird.getName() + " eats seeds");
        }
    
        @Override
        public void visit(Puppy puppy) {
            puppy.feed();
        }
    
        @Override
        public void visit(Kitten kitten) {
            kitten.feed();
        }
    }
    
    public class TrainingVisitor implements AnimalVisitor {
        @Override
        public void visit(Dog dog) {
            dog.fetch();
        }
    
        @Override
        public void visit(Cat cat) {
            cat.climb();
        }
    
        @Override
        public void visit(Bird bird) {
            bird.buildNest();
        }
    
        @Override
        public void visit(Puppy puppy) {
            puppy.learnTrick("sit");
        }
    
        @Override
        public void visit(Kitten kitten) {
            kitten.learnTrick("come");
        }
    }
    

Testing

  1. Zoo Tests
    @Test
    public void testZooOperations() {
        Zoo zoo = new Zoo();
    
        // Add animals
        Dog dog = new Dog("Rex", 3, "German Shepherd");
        Cat cat = new Cat("Whiskers", 2, true);
        Bird bird = new Bird("Tweety", 1, "Canary", true);
        Puppy puppy = new Puppy("Max", 1, "Labrador", false);
        Kitten kitten = new Kitten("Luna", 1, true, true);
    
        zoo.addAnimal(dog);
        zoo.addAnimal(cat);
        zoo.addAnimal(bird);
        zoo.addAnimal(puppy);
        zoo.addAnimal(kitten);
    
        // Test animal sounds
        assertEquals("Woof!", zoo.getAnimal("Rex").makeSound());
        assertEquals("Meow!", zoo.getAnimal("Whiskers").makeSound());
        assertEquals("Tweet!", zoo.getAnimal("Tweety").makeSound());
    
        // Test training
        zoo.trainAnimal("Max", "sit");
        assertTrue(zoo.getAnimal("Max").getTricks().contains("sit"));
    
        // Test visitor pattern
        AnimalVisitor feedingVisitor = new FeedingVisitor();
        zoo.getAnimal("Rex").accept(feedingVisitor);
    }
    

Usage Example

```java public class Main { public static void main(String[] args) { Zoo zoo = new Zoo();

    // Create animals
    Dog dog = new Dog("Rex", 3, "German Shepherd");
    Cat cat = new Cat("Whiskers", 2, true);
    Bird bird = new Bird("Tweety", 1, "Canary", true);
    Puppy puppy = new Puppy("Max", 1, "Labrador", false);
    Kitten kitten = new Kitten("Luna", 1, true, true);

    // Add to zoo
    zoo.addAnimal(dog);
    zoo.addAnimal(cat);
    zoo.addAnimal(bird);
    zoo.addAnimal(puppy);
    zoo.addAnimal(kitten);

    // Make all animals sound
    zoo.makeAllAnimalsSound();

    // Train animals
    zoo.trainAnimal("Max", "sit");
    zoo.trainAnimal("Luna", "come");

    // Use visitor pattern
    AnimalVisitor feedingVisitor = new FeedingVisitor();
    AnimalVisitor trainingVisitor = new TrainingVisitor();

    for (Animal animal : zoo.getAnimalsByType(Animal.class)) {
        animal.accept(feedingVisitor);
        animal.accept(trainingVisitor);
    }
}

}