Constructor Chain with super
Problem
Build these classes: Animal; Dog and Cat (both extend Animal); Puppy (extends Dog); Robot (no parent). Creating an object calls the constructors from the top parent down to the class itself, and each constructor adds its own class name to a shared log. For every input line (a class name) create one object and print its log, with the names joined by ->. For example, creating a Puppy prints Animal -> Dog -> Puppy.
Constraints
- 1 <= lines <= 10^4
Examples
Input
Dog Puppy Robot
Output
Animal -> Dog Animal -> Dog -> Puppy Robot
Solutions
A subclass constructor must make sure that the parent part of the object is built first, because the child may use the parent's fields. In Java the call super(...) must be the first statement of the constructor; if you do not write it, Java calls the parent's no-argument constructor for you.
/*
* Problem : Process lines.
* Input : Several lines.
* Output : One log per line.
* Approach: Class hierarchy.
* Time : O(n)
* Space : O(n)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// Step 1: Every constructor first calls the parent constructor with super(log). Then it adds its own name.
static class Animal {
Animal(java.util.List<String> log) {
log.add("Animal");
}
}
static class Dog extends Animal {
Dog(java.util.List<String> log) {
super(log);
log.add("Dog");
}
}
static class Cat extends Animal {
Cat(java.util.List<String> log) {
super(log);
log.add("Cat");
}
}
static class Puppy extends Dog {
Puppy(java.util.List<String> log) {
super(log);
log.add("Puppy");
}
}
static class Robot {
Robot(java.util.List<String> log) {
log.add("Robot");
}
}
// This method solves the task. It receives the input and returns the answer.
static String[] solve(String[] lines) {
String[] output = new String[lines.length];
for (int i = 0; i < lines.length; i++) {
java.util.List<String> log = new java.util.ArrayList<>();
// Step 2: Creating one object runs the whole constructor chain once.
switch (lines[i]) {
case "Animal":
new Animal(log);
break;
case "Dog":
new Dog(log);
break;
case "Puppy":
new Puppy(log);
break;
case "Cat":
new Cat(log);
break;
default:
new Robot(log);
}
output[i] = String.join(" -> ", log);
}
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)
- Why is the parent constructor called first?