Este es mi primer post. Soy bastante nuevo en esto.
Estoy haciendo una clase, supongamos “animales”. Dentro de la misma tengo un procedimiento “void hijo”, que crea una copia de si misma con algunas variaciones y la agrega una arraylist de la cual forman parte todos los “animales”. Por otro lado tengo una clase “perro” que extiende la clase “animales”. Cuando llamo al procedimiento “hijo” de la clase “perro” me crea otro “animal” y no un perro. Por ahora lo soluciono copiando todo el procedimiento “hijo” en la subclase y cambiando de “Animal nuevo = New Animal;” por “Perro nuevo = New Perro”. Estoy seguro que tiene que haber una mejor manera. Si alguien me puede ayudar se lo agradecería.
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!
I really appreciate your response. I thanks you for taking the job of translating my question. I understand english! I´m not so good talking it, or writing it. I´m trying to understand your response, and din´t do it yet! I don´t know how to publish code in the right format, but more or less this is what i’m doing. I would spect to have:
Ball
Subclass
Ball
Subclass
but I get:
Ball
Subclass
Ball
Ball
/**
*
*
* aledante@hotmail.com
*/
import org.gicentre.utils.geom.*;
import java.util.*;
HashGrid<Ball> balls;
Set<Ball> paranacer=new HashSet<Ball>();
void setup() {
size(400, 400);
balls = new HashGrid(width, height, 10);
balls.add(new Ball());
// println(balls);
balls.add(new Subclass());
// println(balls);
}
void draw() {
// I add all to a set.
for (Iterator<Ball> iterator = balls.iterator(); iterator.hasNext(); ) {
Ball ball = iterator.next();
paranacer.add(ball);
}
// I make to execute hijo on all the ser.
for (Iterator<Ball> iterator = paranacer.iterator(); iterator.hasNext(); ) {
Ball ball = iterator.next();
ball.hijo();
}
for (Iterator<Ball> iterator = balls.iterator(); iterator.hasNext(); ) {
Ball ball = iterator.next();
println(ball.nombre);
}
exit();
}
class Ball implements Locatable {
PVector location;
String nombre;
Ball() {
location = new PVector(40, 20);
nombre ="Ball";
}
void hijo() {
Ball hijo = new Ball();
balls.add(hijo);
}
public PVector getLocation()
{
return location;
}
}
class Subclass extends Ball {
Subclass() {
super();
nombre="Subclass";
}
}
Notice I had to do: hijo.location = location.get();. Here’s the reason why:
Your class Ball got 2 fields: location & nombre.
The 1st refers to a PVector, while the 2nd refers to a String.
Datatype String is immutable. Its content can’t be changed (at least not w/o some hardcore hacking ).
However, datatype PVector is mutable. Its fields x, y & z can be freely reassigned.
If we don’t also clone each mutable field from a class when we call clone(), modifying those mutable fields will reflect on both the original object and all of its clones!
That’s why I invoke the method PVector::get() over the cloned field location, so the original and the cloned field location won’t share the same PVector object:
Thanks again. Great answer, extremely complete, and clear.
Some questions:
I made the example code very simple to explain my problem. My class have several variables. Some int, another PVector, some float, and another class. Only PVector and class are mutables, isn´t it?
So
@Override Bola clone() {
try {
final Bola pelota = (Bola) super.clone();
pelota.location = location.get();
pelota.vel = location.get(); // This is the other PVector
pelota.comp=comp.copia(); // This is a method that I have to make to copy my other class
return pelota;
}
Is it correct?
Is it necessary to use “@Override”. In Processing reference says that is not… But I see it a lot.
Hello again,
Excuse me. But i can not get ir right.
In the extended class I want to make some changes over child objects.
Why i cannot invoke clone method on extended class? Why I cannot invoke super class?
I show the code you send me with the modifications i would like to do, that shows me mismatch errors.
The problem is in the last few lines.
/**
* Cloneable Locatable (v1.0)
* GoToLoop (2019/Jan/)
* Discourse.Processing.org/t/problema-con-class-extend-y-herencia/11204/4
*/
import org.gicentre.utils.geom.HashGrid;
import org.gicentre.utils.geom.Locatable;
import java.util.List;
import java.util.Set;
static final int SIZE = 10;
final List<Bola> temp = new ArrayList<Bola>();
Set<Bola> pelotas;
// HashGrid<Bola> pelotas;
void setup() {
size(400, 400);
noLoop();
pelotas = new HashGrid<Bola>(width, height, SIZE);
pelotas.add(new Bola());
pelotas.add(new Bolita());
}
void draw() {
background((color) random(#000000));
getSurface().setTitle("Frame: " + frameCount);
println(ENTER + "Pelotas: " + pelotas.size());
for (final Bola b : pelotas) println(b);
}
void mousePressed() {
temp.clear();
for (final Bola b : pelotas) temp.add(b.hijo());
pelotas.addAll(temp);
redraw = true;
}
class Bola implements Locatable, Cloneable {
PVector location = new PVector(40, 20);
String nombre = getClass().getSimpleName();
Bola hijo() {
Bola hijo=clone();
return hijo;
}
@Override Bola clone() {
try {
final Bola pelota = (Bola) super.clone();
pelota.location = location.get();
return pelota;
}
catch (final CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
@Override PVector getLocation() {
return location;
}
@Override String toString() {
return nombre + ": " + location;
}
}
class Bolita extends Bola {
Bolita hijo() {
Bolita hijo=super.hijo();
hijo.nombre=hijo.nombre+"2";
return hijo;
}
Bolita tween() {
return clone();
}
}
Obviously, method Bola::hijo() returns an object of datatype Bola.
And it can’t be converted to its derived datatype Bolita.
However, it doesn’t need to, b/c the inherited field nombre exists in datatype Bola too:
class Bolita extends Bola {
@Override Bola hijo() {
final Bola hijo = super.hijo();
hijo.nombre += '2';
return hijo;
}
}
However, in case subclass Bolita would add its own fields, besides those it had inherited from Bola, you’d probably need to @OverrideBola::clone() in subclass Bolita, if any of those new fields happen to be mutable.