Problema con Class, extend y herencia

Disclaimer: I know English & Portuguese only. :expressionless:

And although I can understand Spanish more or less, still I can’t properly reply using it, sorry. :disappointed:

Anyways, we can always count on Google Translate, right? :relieved:

Indeed, if your method Animal::hijo() is something like this:

class Animal {
  Animal hijo(final String name) {
    return new Animal(name);
  }
}

And you’ve got a class that extends it:

class Perro extends Animal {
  Perro(final String name) {
    super(name);
  }
}

Java won’t “automagically” upgrade the datatype Animal in return new Animal(name); to the datatype of that subclass like return new Perro(name); in any way! :cry:

As a workaround, we could use Java reflection techniques in order to always instantiate the current subclass’ Constructor: :building_construction:
Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/lang/reflect/Constructor.html

However, reflection is complicated! And thus it should be used only if there’s no other alternative: :warning:

And a simpler alternative is to implement the Cloneable interface and its clone() method: :bulb:
Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Cloneable.html
Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Object.html#clone()

Here’s an example of a class named Pair which implements Cloneable: :nerd_face:

And inspired by my previous sketch above, here’s “Cloneable Inheritance”: :cowboy_hat_face:

/**
 * Cloneable Inheritance (v1.0.1)
 * GoToLoop (2019/May/13)
 * Discourse.Processing.org/t/problema-con-class-extend-y-herencia/11204/2
 */

import java.util.List;
final List<Animal> animales = new ArrayList<Animal>();

void setup() {
  animales.add(new Animal("Madre"));
  println(animales);

  animales.add(animales.get(animales.size() - 1).hijo("Hijo"));
  println(animales);

  animales.add(new Perro("Rex"));
  println(animales);

  animales.add(animales.get(animales.size() - 1).hijo("Perla"));
  println(animales);

  exit();
}

class Animal implements Cloneable {
  String name;

  Animal() {
  }

  Animal(final String name) {
    set(name);
  }

  Animal set(final String nick) {
    name = nick;
    return this;
  }

  Animal hijo(final String name) {
    //return new Animal(name);
    return clone().set(name);
  }

  @Override Animal clone() {
    try {
      return (Animal) super.clone();
    }
    catch (final CloneNotSupportedException e) {
      throw new RuntimeException(e);
    }
  }

  @Override String toString() {
    return name + " el " + getClass().getSimpleName();
  }
}

class Perro extends Animal {
  Perro() {
  }

  Perro(final String name) {
    super(name);
  }
}
2 Likes