Reputation: 47
I'm experimenting with two different methods to get a bidimensional array to rotate. Both work when inheritance isn't involved, but as soon as I extend the class, one of them gives weird results.
This is the one that always works:
This is what doesn't work:
However, the results I get from this latter one indicate that it's like the copy array it's initialized everytime a new line in executes, so the copy array reflects the changes I make in the original array, rather than staying the same and letting me copy each cell.
Here's examples, assuming the array I'm trying to rotate is a piece of Tetris.
This does not work:
public abstract class Piece {
private int y;
private int x;
private String[][] tetromino;
public void setTetromino(String[][] a) { tetromino = a; }
public void rotate()
{
String[][] copy = tetromino;
tetramino[0][0] = copy[0][2];
tetramino[0][1] = copy[1][2];
tetramino[0][2] = copy[2][2];
tetramino[1][0] = copy[0][1];
tetramino[1][2] = copy[2][1];
tetramino[2][0] = copy[0][0];
tetramino[2][1] = copy[1][0];
tetramino[2][2] = copy[2][0];
}
public void print()
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
System.out.print(tetromino[i][j]);
}
System.out.println();
}
}
}
And its subclass:
public class TPiece extends Piece {
String[][] a = {{ "1", "2", "3" },
{ "4", "5", "6" },
{ "7", "8", "9" }};
public TPiece()
{
setTetromino(a);
}
public static void main(String[] args)
{
TPiece T = new TPiece();
T.print();
T.rotate();
T.print();
}
}
Output:
123
456
789
369
658
363
Not rotated!
Now, for the working one, here's the changes to rotate() (everything else stays the same):
public void rotate() {
String[][] copy = new String[3][3];
copy[0][0] = tetromino[0][2];
copy[0][1] = tetromino[1][2];
copy[0][2] = tetromino[2][2];
copy[1][0] = tetromino[0][1];
copy[1][1] = tetromino[1][1];
copy[1][2] = tetromino[2][1];
copy[2][0] = tetromino[0][0];
copy[2][1] = tetromino[1][0];
copy[2][2] = tetromino[2][0];
tetromino = copy;
}
Output:
123
456
789
369
258
147
Rotated as intended.
Can anyone explain why?
Upvotes: 0
Views: 76
Reputation: 190
It's not polymorphism that's the issue here, it's objects and what is happening. The way Java works is that when we create a new object, we have some reference to that object. Let's use a picture found in this answer.
While we're not using a Person object, the same principles hold for any object (keep in mind, arrays are objects in Java). What is happening is we create some person object. For this, we'll keep it simple and say the line is Person person = new Person();
. Pretty standard. Let's say we make another person though, and this time, we say Person person2 = person;
Perfectly legal, and this shows what is happening in the picture above; we have 2 references pointing to the same object.
The reason that long-winded explanation of object references is here is because that is what is happening in your code. In the rotate()
method, the first line is String[][] copy = tetromino;
. This will set copy equal to what tetromino is, and every change made in copy is also made in tetromino. I'm not sure what IDE you are using, but I know Eclipse has a debugger where you can step through a function and check values as you go. Doing so and checking the value of copy
and tetramino
will show the change happening in each at every line.
I fixed your code to show a working example.
Piece:
public abstract class Piece {
private int y;
private int x;
private String[][] tetramino;
public void setTetramino(String[][] a) { tetramino = a; }
public void rotate()
{
String[][] copy = new String[3][3];
copy[0][0] = tetramino[0][2];
copy[0][1] = tetramino[1][2];
copy[0][2] = tetramino[2][2];
copy[1][0] = tetramino[0][1];
copy[1][1] = tetramino[1][1];
copy[1][2] = tetramino[2][1];
copy[2][0] = tetramino[0][0];
copy[2][1] = tetramino[1][0];
copy[2][2] = tetramino[2][0];
setTetramino(copy);
}
public void print()
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
System.out.print(tetramino[i][j]);
}
System.out.println();
}
}
}
TPiece:
public class TPiece extends Piece {
String[][] a = {{ "1", "2", "3" },
{ "4", "5", "6" },
{ "7", "8", "9" }};
public TPiece()
{
setTetramino(a);
}
public static void main(String[] args)
{
TPiece T = new TPiece();
T.print();
T.rotate();
T.print();
}
}
As you can see, copy is now just an empty 2d array, and at the end, the setTetramino
method is called.
Upvotes: 2
Reputation: 1648
Java have Objects and Primitive data types. object data types keep the reference in your programme but the actual object in the heap. so in first case,
String[][] copy = tetromino;
tetramino[0][0] = copy[0][2];
There your copy and tetramino both arrays points to same array.
tetramino[0][0] = copy[0][2];
tetramino[0][1] = copy[1][2];
tetramino[0][2] = copy[2][2];
tetramino[1][0] = copy[0][1];
is equals to
copy[0][0] = copy[0][2];
copy[0][1] = copy[1][2];
copy[0][2] = copy[2][2];
copy[1][0] = copy[0][1];
but in second scenario you have initialized a new array that's why you got correct results.If you want to working on first method you have to used to deep copy instead of shallow copy (not only reference but you want to copy objects). use this link to learn how to deep copy. Hope this will help :)
Upvotes: 3