I'm trying to create a program that starts with a Piece class. For the purpose of the exercise every other class extends Piece. The other classes contain methods for moving the pieces, either one space or n spaces.
All of the pieces are stored in a 2D array which the use to move around.
My problem is that if i make an array of Pieces I cannot access the move methods as they are stored in the subclasses. I also can't just cast the object because i have 4 different types that the user can ask to move.
This is the code that adds a piece to the board
//adds a piece based on given type, but only if the space is clear (null)
public void addpiece(String type, String n, String c, int x, int y){
if(board[x][y] == null){
if(type == "FastFlexible"){
board[x][y] = new FastFlexiblePiece(n,c,x,y);
}
else if(type == "FastPiece"){
board[x][y] = new FastPiece(n,c,x,y);
}
else if(type == "SlowFlexible"){
board[x][y] = new SlowFlexiblePiece(n,c,x,y);
}
else if(type == "SlowPiece"){
board[x][y] = new SlowPiece(n,c,x,y);
}
else{
System.out.println("Invaild type");
}
}
}
And this is the code that tries to move the piece, the error I get is because the parent Piece doesn't have a move method, but I can't figure out a way to get the pieces to cast correctly
//Move a piece, two method one for fast and one for slow
public void movePiece(int x, int y, String direction){
if(board[x][y] != null){
if(board[x][y].getType().equals("SlowPiece")){
board[x][y] = board[x][y].move(direction);
}
else if(board[x][y].getType().equals("SlowFlexible")){
board[x][y] = board[x][y].move(direction);
}
}
}
There is another similar method for fast pieces.
Constructor for the slowPiece:
//Constructor
public SlowPiece(String n, String c, int x, int y){
super(n,c,x,y);
this.setType("SlowPiece");
}
But the code doesn't notice what type any of the Pieces are and so I can't cast them correctly
The very aim of Polymorphism is to avoid writing code like the implementation specified for public void movePiece(int x, int y, String direction){.
board[x][y] can refer to SuperType Piece and any of its SubTypes like the SlowPiece, SlowFlexible, FastPiece, FastFlexible. Piece can have the abstract move behavior specified in the definition of the class, without having to provide the implementation. All the SubTypes of Piece class provide their own implementation for move method.
The method public void movePiece(int x, int y, String direction) would simply boil down to this :
public void movePiece(int x, int y, String direction){
board[x][y].move(direction);
}
At runtime, move method is dynamically dispatched depending upon the SubType of Piece class.
My suggestion is to add an abstract method to the parent Piece class.
public class Piece{
public abstract void move();
}
NOTE: now you can't directly instantiate a Piece. This code is illegal:
Piece p = new Piece();
Related
I wrote half of it but cannot get it 100% correct. Can anyone help me with it?
Here is my problem:
Write a parameterized class Triple that represents a trio of some type (eg, the Three of String, the Integer , etc.). For Triple class define:
-getElement method that receives an integer number (1,2 or 3) and returns the corresponding member. In the case of an illegal argument, throw an IllegalArgumentExpression exception
-setElement that receives two arguments: an integer number (1, 2 or 3) and the value to be placed as a member of the three in the corresponding position (eg, setElement(2,3) sets 3 to y value of trio)
-a constructor with 3 arguments that set the initial values of the Triple
Then you should write the ComparableTriple class, which represents the triplet. Members of triplet must be comparable (implement Comparable interface). Then expand the ComparableTriple class to implement the Comparable interface, so that triplets can be comparable by positions. For example ,(2,6,1) is in the rank before (3,4,5) but behind (2,6, -4). Same template can be applied to String etc.
Example of main code:
Triple t1 = new ComparableTriple<>(2, 6, 1);
int x = t1.compareTo(t1); // should be 0
//Triple class I wrote
public class Triple<T> {
T x, y, z;
public Triple(T x, T y, T z) {
this.x = x;
this.y = y;
this.z = z;
}
public T getElement(int position) {
if (position == 1) {
return x;
} else if (position == 2) {
return y;
} else if (position == 3) {
return z;
} else throw new IllegalArgumentException();
}
public void setElement(int position, T value) {
if (position == 1) {
x = value;
} else if (position == 2) {
y = value;
} else if (position == 3) {
z = value;
} else throw new IllegalArgumentException(); }
}
I tried writing ComparableTriple overriding CompareTo method but couldn't find the exact solution.
It's not so complicated but I'm new to Generics and can't figure some things out.
Can anyone help me about the rest of code?
public class Triple<T> implements Comparable<Triple<T>> {
... your code here
// functional interface Comparable will force you to override the method
}
But you may want to have some kind of superclass that T extends so you can access fields for the compare.
Example:
public class Triple<T extends Number> implements Comparable<Triple<T>>
There is of course the inline compare with Collections.sort(comparable) if you don't want to commit to what T is.
That should get you started. Post back/edit if you get stuck.
Cheers.
(And this is not a solution by intent). Generics are a pain and need to be slogged through to get good at.
I know this question has been already asked here, but I fail to understand the "Why" part.
Let us take the following example:
public class First {
First() {
System.out.println(super.getClass());
}
}
public class Second extends First {
Second() {
System.out.println(super.getClass());
}
}
public class Third extends Second {
Third() {
System.out.println(super.getClass());
}
}
When I instantiate an Object of type Third:
public class Main {
public static void main(String[] args) {
Third third = new Third();
}
}
The output is:
class Third
class Third
class Third
And what I expected was (Thinking that super.getClass() should return the name of parent class):
class java.lang.Object
class First
class Second
Which shows that I don't understand how does Inheritance actually work in Java. Kindly help me in getting the right concept in my head.
EDIT
My actual intention was to understand how inheritance actually works (which has been explained very well by Jeff), instead of getting the expected output.
This doubt arose when I was trying to the understand why the following code worked (More specifically, why does super.equals(point3d) worked as it has been passed an object of type Point3D)
public class Main {
public static void main(String[] args) {
Point3D p1 = new Point3D(1, 2, 3);
Point3D p2 = new Point3D(1, 2, 3);
System.out.println(p1.equals(p2)); // Output: true
}
}
public class Point {
private int x;
private int y;
public Point() {
this.x = 0;
this.y = 0;
}
public Point(int x, int y) {
this.x = x;
this.y = y;
}
#Override
public boolean equals(Object object) {
if (object != null && object.getClass() == this.getClass()) {
Point point = (Point) object;
return point.x == this.x && point.y == this.y;
} else {
return false;
}
}
}
public class Point3D extends Point {
private int z;
public Point3D() {
this.z = 0;
}
public Point3D(int x, int y, int z) {
super(x, y);
this.z = z;
}
#Override
public boolean equals(Object object) {
if (object != null && object.getClass() == this.getClass()) {
Point3D point3D = (Point3D) object;
return super.equals(point3D) && point3D.z == this.z; // Had doubt here
} else {
return false;
}
}
}
It is important to recognize that there is exactly one object here with one reference. It can be tempting to present it as though the superclass is a separate instance of Second residing within your instance of Third, but it is not true; there is no way to refer to that instance because it does not exist.
To be clear: It is not the case that within Third there is a hidden instance of Second to which super refers, and within Second there is a First, and within First there is an Object. Instead, there is a single object that is able to behave as an Object, First, Second, or Third. Regardless of the type of the local variable or reference ("static type"), the instance itself has a "runtime type", which is Third.
The only thing super can do for you is to deliberately invoke a member that belongs to a superclass (JLS 15.11.2) that may be hidden by overriding or naming. This does nothing here, because getClass() is a final method declared on Object. getClass has documentation that it "Returns the runtime class of this Object" (docs). There can be no varying implementation, so you will always receive the type Third as you do in your question.
UPDATE: Unlike getClass, equals is non-final, and can be overridden. Point.equals ensures that the Class returned by getClass is equal, and that x and y are equal. Rather than writing an entirely different implementation of equals, Point3D defers to the Point's definition of equals and additionally checks that the z field is equal, which works because Point checks that object.getClass() == this.getClass(), not that object.getClass() == Point.class. It could not do this simply by calling equals, because that would use the Point3D.equals implementation; instead it has to call super.equals to see how Point would calculate equals.
However, I hope this is an example in a lesson, because polymorphism asserts that a Point3D is-a Point and can do whatever a Point can do (see the Liskov Substitution Principle). For Point and Point3D, this could be misleading: You could write a method double distanceBetween(Point a, Point b) that works as expected using 2D points but gives an incorrect result when using 3D points. In real environments, you'll need to be careful about what your class hierarchies and what they imply.
getClass() is a method on Object. There's not a separate one for each of your subclasses. If you want to go up the chain like that, call getSuperclass() on the result of getClass().
I'm writing a program that will need to use a limited set of Points to process an image. I figure that I would implement it as an immutable/singleton style class. Before going on to build more of the complex logic surrounding the class I wanted to get an opinion about the core class.
import org.apache.commons.lang3.builder.HashCodeBuilder;
import java.util.HashMap;
public class Point {
private final int x,y;
private final int hashCode;
private static final HashMap<int[],Point> points = new HashMap<>();
private Point(int x,int y){
this.x = x;
this.y = y;
this.hashCode = new HashCodeBuilder().append(x).append(y).toHashCode();
}
public static Point getPoint(int x,int y){
int [] candidate = new int[]{x,y};
if(points.containsKey((candidate))){
return points.get(candidate);
}
Point newPoint = new Point(x,y);
points.put(candidate, newPoint);
return newPoint;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
#Override
public int hashCode(){
return hashCode;
}
#Override
public boolean equals(Object p){
return this == p;
}
}
I'm going to be using the class to do at least the following functions:
Map different channels in an image by this Point class
Define some static cached custom NavigableSets for ease of traversal
Various Helper functions. In example, get all Points surrounding a Point
Given the information provided, what are some downsides of the provided implementation?
Note: Putting the bulleted list before the code block breaks the display of the code block. Bug?
I think your caching "singletony" stuff may be pointless.
It doesn't save on object creation, as you will always create a candidate[] each time you ask for a Point. And, unless the Point gets reused, you use the memory for candidate and the Map.Entry in your HashMap. So, very roughly speaking, unless each Point gets reused three times, your caching uses more memory. And it always uses a more time.
If you don't cache, change your equals of course.
p.s. the rest seems fine, and immutable is good. You could consider making x and y public final to be more compatible with other Point implementations.
If you are worried about the occupied memory, there is another way to deal with it.
I assuming you have limited dimension for your points, I would suggest to combine your x & y in one variable of long (in case your dimensions is 32 ints long), or even int (if you can fit one dimensions in 16 bit), this way you'll get boost in performance & memory.
Other option is to use int[] array of your coordinates for a point, although that would take more space (since you would have to keep additional pointer reference).
Factory method in your implementation, will work only on single threaded applications, if you have multiple threads creating points, you would need to have some concurrency control in place. This would eat up your resources, because you would effectively need to lock on each point creation.
Another reason, why this Factory method is a bad idea, is that int[] arrays do not override equals and hashCode, you can try to create 2 arrays with same content, to check. So your HashMap would not simply work, and instead of saving memory you would not only create a new Point each time, but also add an entry to your HashMap and perform unnecessary calculations.
So either use Java primitives, or just create a new immutable Point each time if you need too, and go with it, don't overcomplicate with factoryMethods.
You had the right idea of making the Point class immutable but then you went and complicated things with the instance cache. It is not thread safe and it will leak memory because once a Point is created it will forever stay in the hashmap and will never be garbage collected.
Why not keep it simple and make a regular boring value class? Your IDE will even generate it for you.
Then, if you really really really want to have an instance cache, use Guava's Interner class instead of rolling your own. The result will look something like this:
public class Point {
final int x;
final int y;
private Point(int x, int y) {
this.x = x;
this.y = y;
}
static Interner<Point> instanceCache = Interners.newWeakInterner();
public static Point of(int x, int y) {
return instanceCache.intern(new Point(x,y));
}
public int getX() { return x; }
public int getY() { return y; }
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Point other = (Point) o;
return this.x == other.x && this.y == other.y;
}
#Override
public int hashCode() { return x * 31 + y; }
}
What I am doing is transposing a c# project to java for practice in writing custom classes.
Unfortunately I cant figure out what the person is doing with "this" keyword inside the constructor.
// C# Code - How is this written in Java?
public Player this[int x, int y]
{
get { return squares[x, y]; }
set { squares[x, y] = value; }
}
I have transposed a lot of the code and am kind of stuck on this. I cant seem to find any information on this particular instance in Java. does anyone have a good lead for me?
That's not in the constructor. That's the declaration of an indexer. The Java equivalent would be something like:
public Player getPlayer(int x, int y)
{
// Note: Java doesn't have "real" multidimensional arrays,
// only arrays of arrays.
return squares[x][y];
}
public Player setPlayer(int x, int y, Player player)
{
squares[x][y] = player;
}
This is Using Indexers (C#).
This blog has some ideas of how to port the C# indexer to java code.
Basically it can be realized in a java getter/setter:
public Player get(int x, int y) { return squares[x][y];}
public Player set(int x, int y, Player p) { squares[x][y] = p;}
That's not a constructor, that's an indexer. Basically, this definition allows you to do:
Player playerAtOrigin = myGameBoard[0, 0];
In Java, only arrays have an indexer (e.g. myArray[i]), you cannot define your own indexers. Most likely, you'll want to translated this into two methods getPlayerAt(int x, int y) and setPlayerAt(int x, int y, Player player).
I am getting a syntax error "insert } to complete ClassBody.
This code works ok/ error free:
import java.awt.Rectangle;
class Trigger
{
Type type;
long time;
ObjectID controlType;
int controlNum;
int resType, resNum;
Rectangle location;
enum Type {TIMED, CONTROLED, LOCATION, RESOURCE};
Trigger()
{
}
}
However when I add in constructors like this I get the error:
class Trigger
{
Type type;
long time;
ObjectID controlType;
int controlNum;
int resType, resNum;
Rectangle location;
enum Type {TIMED, CONTROLED, LOCATION, RESOURCE}; //I get the error on this line
Trigger(Type.TIMED, long t)
{
time = t;
}
Trigger(Type.CONTROLLED, int c)
{
controlNum= c;
}
Trigger(Type.LOCATION, int locx, int locy, int w, int h)
{
location = new Rectangle(locx, locy, w, h);
}
Trigger(Type.RESOURCE, int resT, int resN)
{
resType = resT;
resNum = resN;
}
}
**Note that I am writing this code in processing!
also if I move the enum line to the top (above "Type type;") then the error message jumps to the line "Rectangle location;"
so what is going on here? I don't understand why I do not get an error for the first code but i do for the second!
Update
ok I changed the code to make the enum initialize the type variable in each constructor. This is going to be for an rts I am helping to design for a class project. There is another class called GameEvent that has have an instance of trigger in it and an array list of actions. The triggers will be uploaded from a file and then the actions will be hardcoded ( I know bad style but there are only 3 missions and the TA said that we wouldn't be losing marks for doing that). So children classes sounds like a good idea. But how come it isn't working as is?
here's the updated code:
import java.awt.Rectangle;
class Trigger
{
Type type;
long time;
FCObjectID controlType;
int controlNum;
int resType, resNum;
Rectangle location;
enum Type {TIMED, CONTROLED, LOCATION, RESOURCE};
Trigger(Type.TIMED, long t)
{
type = TIMED;
time = t;
}
Trigger(Type.CONTROLLED, int c)
{
type = CONTROLED;
controlNum= c;
}
Trigger(Type.LOCATION, int locx, int locy, int w, int h)
{
type = LOCATION;
location = new Rectangle(locx, locy, w, h);
}
Trigger(Type.RESOURCE, int resT, int resN)
{
type = RESOURCE;
resType = resT;
resNum = resN;
}
}
Your constructors are incorrect. For example:
Trigger(Type.LOCATION, int locx, int locy, int w, int h)
What do you expect the Type.LOCATION part to do in the parameter list? Each parameter is meant to be a type followed by the name of the parameter (as int locx etc are, correctly).
Were you trying to add different constructors depending on whether the caller was trying to specify a location, a time etc? If so, that's definitely not how you do it... but it sounds like you probably want separate classes for each of those cases anyway.
I would advise against writing your constructors this way.
Your object ends up in different degrees of unusable state depending on which constructor you call. An object ought to be 100% ready to go after construction, without doing anything to surprise clients.
Write one constructor that initializes ALL the member variables, and then call "this" from the others with sensible default values.
You can't use Enum like this. When you create an Enum, you create a Type, so your constructor must take a variable which is the type of your Enum, you can't "force" it like this.
Trigget(Type t, [others arguments]) {
}
I don't grasp what you're trying to do, but you should read some documentation about Enums : http://download.oracle.com/javase/1.5.0/docs/guide/language/enums.html
And it seems to me that you better do some inheritance of your Trigger class. It's not really OO to put a lot of different fields in a class and initialize them depending on some Enum type.
You can easily have a parent Trigger class and then create a children for each Trigger type you need.
Your code doesn't make sense. The argument list for a method (including constructors) must be a list of typed variables, not values. Type.TIMED is a value, not a type!
k I changed my constructors to this and it works:
Trigger(Type tT, long t, int c, int locx, int locy, int w, int h, int resT, int resN)
{
type = tT;
if (type == Type.TIMED)
time = t;
else if (type == Type.CONTROLLED)
controlNum = c;
else if (type == Type.LOCATION)
location = new Rectangle(locx, locy, w, h);
else if (type == Type.RESOURCE)
{
resType = resT;
resNum = resN;
}
}