Animal Sounds with an Interface
Problem
Each input line is an animal: dog, cat or cow. Print its sound: Woof, Meow or Moo. For any other animal print unknown animal. Make one class for each animal that follows a common interface.
Constraints
- 1 <= lines <= 10^4
Examples
Input
dog cat fish
Output
Woof Meow unknown animal
Solutions
The calling code works with the interface only. To add a new animal you add a class and one map entry; the loop does not change. Object.hasOwn prevents a name like constructor from being found in a plain object.
/*
* Problem : Process lines.
* Input : Several lines.
* Output : One sound per line.
* Approach: Classes with a common method.
* Time : O(n)
* Space : O(n)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// Step 1: An interface says what every animal can do. It has no code about how.
interface Animal {
String sound();
}
static class Dog implements Animal {
public String sound() {
return "Woof";
}
}
static class Cat implements Animal {
public String sound() {
return "Meow";
}
}
static class Cow implements Animal {
public String sound() {
return "Moo";
}
}
// This method solves the task. It receives the input and returns the answer.
static String[] solve(String[] lines) {
// Step 2: A map from the name to a new animal object. Every value has the type Animal.
java.util.Map<String, java.util.function.Supplier<Animal>> animals = new java.util.HashMap<>();
animals.put("dog", Dog::new);
animals.put("cat", Cat::new);
animals.put("cow", Cow::new);
String[] output = new String[lines.length];
for (int i = 0; i < lines.length; i++) {
// Step 3: Make the animal and call sound(). We do not check the class: the interface guarantees the method.
java.util.function.Supplier<Animal> maker = animals.get(lines[i]);
output[i] = maker == null ? "unknown animal" : maker.get().sound();
}
return output;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
java.util.List<String> all = new java.util.ArrayList<>();
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (!line.isEmpty()) {
all.add(line);
}
}
String[] lines = all.toArray(new String[0]);
System.out.println(String.join("\n", solve(lines)));
}
}
Hints (1)
- What does the loop need to know about each animal?