I have something like this:
Figures fig = new Line();
on which Line extends Figure. Figure is an abstract class that only has a method getType() that tells me which figure it is by returning a String;
I have 3 types, Rectangle, Circle and Figure. All of them extend Figures.
Now the real question. I store every single one inside of a List<Figures> and I want to get access to some methods on each object like getStartX(); and getStartY(); and I can't, I only can access the methods that are on Figures also.
Your abstract class should define the getStartX and getStartY method. Either abstract if you want Rectangle, Circle and Figure to have a different behaviour and force them to Override those methods. Else just put the method in Figures it'll be available for use (with the appropriate keyword : public/protected depending your needs).
If you want to use methods that are specific to a class you'll need to check of which instance it is. Something like
for (Figures figure: myList) {
int x = figure.getStartX(); // Method common and declared in Figures
if (figure instanceof Circle) {
System.out.println("Oh no a Circle!");
int radius = ((Circle)figure).getRadius();
...
}
}
For your Rectangle/Line you can define an interface with your 2 methods:
public interface HasEndpoints {
int getEndX();
int getEndY();
}
public class Rectangle implements HasEndpoints {
...
public int getEndX() {return endx;}
...
}
for (Figures figure: myList) {
int x = figure.getStartX(); // Method common and declared in Figures
if (figure instanceof HasEndpoints) { // Rectangle and Line will go there
System.out.println("HasEndpoints implementor");
int endX = ((HasEndpoints)figure).getEndX();
...
}
}
You can use instanceof with if...else and cast dynamically your object
Figure fig = new //Circle()/Triangle()/Rectangle();
if( fig instanceof Circle) {
((Circle) fig).getRadius(); //This method is only available in Circle class
}
You can always cast the Figure to Line, but not the best choice. Depending on the problem, you can apply Visitor Pattern or add those methods to Figure, even when the Circle doesn't have a starting and ending point.
For example
public abstract class Figure{
public abstract void visit(FigureVisitor visitor);
}
public class Line extends Figure{
public void visit(FigureVisitor visitor){
visitor.visitLine(this);
}
}
public interface FigureVisitor{
public void visitLine(Line figure);
public void visitCircle(Circle figure);
}
public class StartingPointsVisitor implements FigureVisitor{
private Double startX;
private Double startY;
private Double endX;
private Double endY;
public void visitLine(Line figure){
this.startX = figure.getStartX(); //No cast needed
...
}
public void visitCircle(Circle figure){
//Stub-method
}
//Getters to read the results
}
Is a more complex solution, but as i said, it depends on the problem, and most of the complex remains in the Visitor
Either getStartX() and getStartY() should be declared in Figure class or you need to cast the object to Line class:
Figure figure = figures.get(0);
if ("line".equals(figure.getType())) {
Line line = (Line)figure;
}
Another option is to use reflection. But you still need to be sure, that the requested method can be called.
Related
I can't get my head around the following OOP problem in java:
I have two classes which extend some basic library classes.
class myMovie extends Movie
{
int posi_x;
int posi_y;
...
myMovie(PApplet parent, String filename, int pposi_x, int pposi_y, float pangle, String player)
{
super(parent, filename);
...
}
int getFadeVal()
{
...
}
void fadeOut(int pms)
{
...
}
void fadeIn(int pms)
{
...
}
void exit()
{
...
}
}
class myImage extends PImage
{
// Will get a somehow similar implementation
}
This works as intended. But now I have a "main loop" which draws all of these different objects and therefore i want to simply call the methods of these classes without asking of which type the object next in list is.
For me that means i need some type of head class which contains either a myMovie or a myImage. Something like:
class AnimationObject
{
var child;
...
}
And then in the main loop just calling
AnimationObject[] ani_list;
foreach(AnimationObject ani in ani_list)
{
ani.draw();
}
Of course the problem is that Java doesn't know something like "var". I Could use Object, but then i'd have to always cast the type of the object in the main loop.
Which is the correct approach to this problem? I can't really understand all those Interfaces, Abstract Classes etc. in contrast to my exact problem.
Which is the preferred and correct way to do this?
}
Use a interface for this:
public interface AnimationObject {
void draw();
}
public class myImage extends PImage implements AnimationObject {
[...]
}
public class myMovie extends Movie implements AnimationObject {
[...]
}
And in your main loop use the interface:
AnimationObject[] ani_list;
foreach(AnimationObject ani : ani_list) {
ani.draw();
}
I'm writing a chess game. My basic design is to have a 2d array (8 x 8) consisting of square objects. Squares have a number of fields: int height, int width, Piece piece (null if empty, some type of Piece object otherwise.
NB: Rook, Knight, Bishop, etc. all extend Piece.
Now, I'm getting a little tripped up on how to figure out what moves are legal for a given piece, given my OOP design. Here's what I'm thinking:
1) User clicks square
2) We determine what piece is on square (if empty, return error message)
3) Generate legal moves for that piece on that square
I'm worried about writing code like:
if (clickedSquare.piece.instanceOf(Rook)) {
return Rook.getLegalDestinationSquares(clickedSquare);
} else if (clickedSquare.piece.instanceOf(Bishop)) {
return Bishop.getLegalDestinationSquares(clickedSquare);
} else if...
Which seems really bad. There must be a way to do this that conforms better to OOP but I'm still learning.
Thanks for the help,
Mariogs
You don't need to create that if statement. Just get the current piece on the field and call some method like (getLegalMoves()) or something.
If field is empty - return empty list of allowed moves.
public abstract class Piece {
public abstract List<Field> getFieldsAllowed(Field field);
}
public class Rook extends Piece {
#Override
public List<Field> getFieldsAllowed(Field field) {
// TODO Auto-generated method stub
return null;
}
}
public class Field {
public Piece getPiece() {
// get current piece
}
}
Something like this. Try to find your own solution. This one is not perfect.
public final class Point {
public final int x, y;
public Point (int x, int y){
this.x = x;
this.y = y;
}
}
public abstract class Piece {
private Point location;
protected Piece (Point initial){
this.location = initial;
}
public Point getLocation(){ return location; }
public Point setLocation(Point location){ this.location = location; }
public abstract List<Point> getLegalMoves ();
}
public final class Rook {
public Rook (Point initial){
super(initial);
}
public List<Point> getLegalMoves (){
// you know the current location, and you know you are a Rook,
// so you have all you need to determine the possible points where
// this Rook can go to
}
}
Then in other code, you can do:
List<Point> legalMoves = clickedSquare.piece.getLegalMoves();
which clearly makes abstraction of what actual piece it is acting upon.
If you do need a static method for other purposes, you can define them in each class such as Rook. Delegate the instance methods to the static methods to avoid code duplication. Like this:
public final class Rook {
// constructor etc.
public List<Point> getLegalMoves (){
return Rook.getLegalMoves (getLocation());
}
public static List<Point> getLegalMoves(Point start){
// you know the location (start), and you know this method is for a Rook,
// so you have all you need to determine the possible end points
}
}
However, if you do not need that static method, don't use and don't even write it (or at least don't expose it in the API of the class). Users of your classes will otherwise start to abuse it end will end up writing code as you provided in your start post - those countless if-elses.
By using this solution, you can add more concrete subclasses (Pawn, King, ...) in the future without touching any existing code (that now acts on Piece), which gives you a maintainability advantage compared to your provided approach.
If Rook, Bishop etc are:
public class Rook extends Piece {
#Override
public String getLegalDestinationSquares() {
// returns all leagal Rook squers
return null;
}
}
and Piece is:
public abstract class Piece {
public abstract String getLegalDestinationSquares();
}
Then you might do it like (in your sample):
return clickedSquare.piece.getLegalDestinationSquares();
Return String is just example, probably you should return Collection of squares.
From OOD there are a few critics.
a field is a field even if no figure is on the field. A null-filed therefore does not exists (LSP)!
a figure do never know what moves he can do, this must be set only by the game rules. Create a new class called Rules. Its the responsibility of the rules to know what moves he can do(SRP). A King (for example) must know if he already did a Castling to decide if he can do a Castling, therefore he must know the previous moves, and this breaks the DIP - ah, here we have another class we miss: ChessNotation.
instanceof is usefull when you inherit things, a Rook can not inherit a field (LSP,DIP).
Let's say I have a board game where players can buy the squares that they land on. I have a method in my abstract base class of Squares called this:
public abstract void applyLandOnAffect(Player player);
Then in my class of BuyableSquares I implement this method shown below:
#Override
public void applyLandOnAffect(Player player){
//Offer them the chance buy the square here.
}
Then if they choose to buy the square I want the object to change from a BuyableSquares() into a BoughtSquare(). The code in the BoughtSquare would handle what happens when another player lands on a bought square. But the issue is how and where I should transform it.
I was thinking this type of code:
this = new BoughtSquare();
But it's not accepted syntax.
How do I approach this?
Thanks
If you are using polymorphism to have different processing of Square instances depending on its type, my suggestion is to use State design pattern.
To introduce it in your application you should:
define a new interface named e.g. SquareState with methods that differ depending on the square type
public interface SquareState {
void applyLandOnAffect(Player player);
}
define all square types which will implement this interface and provide the implementation of the methods from the SquareState interface
public AvailableState implements SquareState {
public void applyLandOnAffect(Player player) { // ..
}
}
public BoughtState implements SquareState {
public void applyLandOnAffect(Player player) { // ..
}
}
introduce a new attribute inside the Square class that will store the current state of the square
public class Square {
private SquareState state;
// ..
}
Once you have done that, changing the state of the Square will be a matter of calling:
this.state = new BoughtSquare();
First of all, you can't assign anything to this.
In order to achieve what you want, why not create a flag in the BuyableSquares class, that indicates whether or not the square is bought.
public class BuyableSquares extends Squares {
private boolean bought = false; // by default
//...
public void markAsBought() {
bought = true;
}
}
Once you instantiate an object, you cannot change its class.
An option would that, as both classes already extend a superclass, use that as the reference to the classes so you can easily replace them. So, you store your board as a set (or list or array) of Square, each of them is a BuyableSquare or a BoughtSquare. When a BuyableSquare must be transformed, you replace it from your structure with the correspondent BoughtSquare (of course, a BoughtSquare constructor that takes the original BuyableSquare as a parameter would be advisable).
I agree with the previous post the the State pattern is best. Setup the Square class with a state variable that you can switch to different states when different events happen to that square. Then, have each state encapsulate the behaviors for what happens when a player lands on the square and it is in a particular state. To change states, just reassign a different instance of SquareState to the state variable. A very simple outline would look like this.
interface SquareState{
void applyLandOnAffect(Player player);
}
public class Square{
private SquareState state = new AvailabelState();
}
public AvailableState implements SquareState{
public void applyLandOnAffect(Player player){
...
}
}
public BoughtState implements SquareState{
public void applyLandOnAffect(Player player){
...
}
}
You should just have one class called Square instead of having separate classes for purchased squares and unpurchased squares. Or you can extend Square if you plan on having other types of squares that are not purchasable. Create a boolean value in your class called purchased that's set to false by default. Then when the square is purchased you can set the value to true.
public class PurchaseableSquare extends Square
{
private boolean purchased;
public Square()
{
this.purchased = false;
}
public void purchaseSquare()
{
this.purchased = true;
}
}
This is one of the examples that justify the rule prefer composition over inheritance.
In your case you have Square subtypes where you define the behavior. The problem is that your object can't change class, so it can't be transformed from BuyableSquare to BoughtSquare. A design based on composition would create a new interface for the square's state. So Square has a SquareState. The different behaviors of bought and not bought squares will be defined in different subtypes of the SquareState interface. So when somebody buys a square you just change its state. Something like:
public class Square {
private SquareState state = new Buyable();
public void buyMe() {
this.state=new Bought();
}
}
I'm writing a game engine in Java for Android games and my engine handles collision detection for different shapes. Each shape is its own class (Square, Circle, etc.), and derives from a common abstract parent Collidable. I have a physics manager class which basically checks if any of the existing objects in the game are colliding with another, and then does the appropriate action when collision is detected. The check for collision is implemented inside each physics shape child class as in the code below.
public abstract class Collidable
{
}
public class Square extends Collidable
{
public boolean Collides(Square) {...}
public boolean Collides(Circle) {...}
public boolean Collides(Triangle) {...}
}
public class Circle extends Collidable
{
public boolean Collides(Square) {...}
public boolean Collides(Circle) {...}
public boolean Collides(Triangle) {...}
}
public class Triangle extends Collidable
{
public boolean Collides(Square) {...}
public boolean Collides(Circle) {...}
public boolean Collides(Triangle) {...}
}
public class PhysicsMgr
{
public boolean Collides(Collidable p1, Collidable p2)
{
return p1.Collides(p2);
// This obviously won't work because there is no Collides
// method in Collidable. I want it to somehow call the child's
// method and pass in p2 as its child type rather than as
// a parent. Or somehow do this:
return (p1.child()).Collides(p2.child());
// I know that obviously nothing like this exists.
}
}
I am aware of "instanceof" and really don't want to check the child type of p1 and p2 versus every single collision shape I have. There must be a better way. I'm looking for either a workaround for my current problem, or preferably a redesign of my current collision detection system to avoid this problem altogether.
Thanks!
you should read about the visitor pattern
For starters, I wouldn't make Collidable an abstract class. Even though there are probably good arguments for it; it just seems to me like this is an "is a" situation where a lot of objects could be collidable.
So, that being said, here is what I would recommend:
// Assuming you're working in 2 dimensions
public class Coordinates {
public Coordinates(float x, float y) {
// etc etc etc
}
}
public interface ICollidable {
// Using unusually long name to illustrate point,
// but feel free to rename.
public int getMaxDistanceFromCenterOfMass(Coordinates unitVector);
public Coordinates getCenterOfMass();
}
And then, for Square, Triangle, and Circle, I would implement the interface.
public class Square implements ICollidable {
#Override
public int getMaxDistanceFromCenterOfMass(Coordinates unitVector) {
// Must declare and initialize
return this.lengthOfSide;
}
#Override
public Coordinates getCenterOfMass() {
return this.centerOfMass;
}
}
public class Circle implements ICollidable {
#Override
public int getMaxDistanceFromCenterOfMass(Coordinates unitVector) {
// Must declare and initialize
return this.radius;
}
#Override
public Coordinates getCenterOfMass() {
return this.centerOfMass;
}
}
public class Triangle implements ICollidable {
#Override
public int getMaxDistanceFromCenterOfMass(Coordinates unitVector) {
// Must declare and initialize
return this.lengthOfSide;
}
#Override
public Coordinates getCenterOfMass() {
return this.centerOfMass;
}
}
Then, in your PhysicsMgr...
public class PhysicsMgr {
public boolean Collides(ICollidable p1, ICollidable p2) {
Coordinates cm1 = p1.getCenterOfMass();
Coordinates cm2 = p2.getCenterOfMass();
int length = Math.sqrt(Math.pow(cm1.x - cm2.x, 2) + Math.pow(cm1.y - cm2.y, 2))
// It is a misnomer to use coordinates as a unit vector, but if I defined a
// UnitVector class, it would be exactly the same with the exception of
// the class name for this situation.
Coordinates unitVector = new Coordinates((cm1.x - cm2.x)/length, (cm1.y - cm2.y)/length);
int collisionDistance1 = p1.getMaxDistanceFromCenterOfMass(unitVector);
int collisionDistance2 = p2.getMaxDistanceFromCenterOfMass(unitVector);
return (length - collisionDistance1 - collisionDistance2) <= 0;
}
}
The one major caveat here is that using the maxDistance from center of mass literally will only give you an approximation for the Square and Triangle. To be exact, you will have to declare some orientation, theta, and calculate the distance from the center of mass of the object to the edge along the unit vector (which will be tricky, but exact).
Another thing that is nice about this is that it allows you to easily add other collidable objects as your engine becomes more sophisticated. This also makes it so that none of the objects have to know about each other.
I was a physics TA for 3 years and it was actually how I got my first exposure to programming. If you're interested in the extra work, here is a reference to the book we used: http://matterandinteractions.org/ It is great for programmers because it teaches physics by using coding examples in python (specifically, vpython http://vpython.org/ ). So this would be a very good reference to have for physics programming.
public boolean Collides(Square) {...}
public boolean Collides(Circle) {...}
public boolean Collides(Triangle) {...}
You are going to need separate implementations for the various combinations of shapes (because there is no common algorithm, I think). So at one point, there will be the need to call instanceof. I am afraid having an abstract method or interface method public boolean Collides(Collidable) is not going to help here, and what you have now cannot be significantly improved upon. This is a textbook case of the limitations of OOP, because these collision detection methods cannot be neatly attached to any of the shape classes, they live somewhere in between, in something like your physics manager.
Main purpose of this task is to calculate volumes and surface areas of three dimensional geometric shapes
like, cylinders, cones.
In Java Language
Design your classes as below introducing:
an Interface named “GeometricShapes”
an abstract class named “ThreeDShapes”
two child classes of ThreeDShapes: Cylinders and Cones.
One test class names “TestShapes”
Get the output for volumes and surface areas of cylinders and cones along with respective values of
their appropriate input variables. Try to use toString() method and array. Your classes should be
designed with methods that are required for Object-Oriented programming.
So Far I Have:
package Assignment2;
public interface GeometricShapes {
public void render();
public int[] getPosition();
public void setPosition(int x, int y);
}
package Assignment2;
public abstract class ThreeDShapes implements GeometricShapes
{
public int[] position;
public int[] size;
public ThreeDShapes()
{
}
public int[] getPosition()
{
return position;
}
public void setPosition(int x, int y)
{
position[0] = x;
position[1] = y;
}
}
package Assignment2;
public class Cylinders extends ThreeDShapes
{
public Cylinder()
{
}
public void render()
{
}
}
I don't think this is right and I do not know how to fix it. :( Please help.
Most of the problem solving task is to understanding what is asked from you. Teacher wants to make you show that you know how interfaces, abstract classes and classes are connected, and how do thy contribute to the whole object instance.
There are few things that are assumed from you, but you would just be better of rereading notes provided for you - assuming, that you did not pay attention in the class. My experience shows, that struggling student do need a bit more then just advice to get going - if you need help, find a person who is ace'ing the class and just ask assistance.
But for now, to get you going, this is what part of the assignement could look like
package Assignment2;
import java.util.Arrays;
public class task {
public static interface GeometricShapes {
public double getArea();
public double getVolume();
}
public static abstract class ThreeDShapes implements GeometricShapes {
protected double a, h;
}
public static class Cones extends ThreeDShapes {
#Override public double getArea() {
return Math.PI * this.a * Math.sqrt(a * a + h * h);
}
#Override public double getVolume() {
return (1d / 3d) * Math.PI * Math.pow(a, 2) * a * h;
}
#Override public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Cone [a=").append(a).append("; ").append("h=")
.append(h).append(" ( area=").append(this.getArea())
.append("; volume=").append(this.getVolume()).append(" )]");
return builder.toString();
}
}
public static void main(String[] args) {
System.out.println(Arrays.toString(new ThreeDShapes[] {
new Cones() {{ a = 3; h = 4;}},
new Cones() {{ a = 4; h = 5;}}
}));
}
}
Output:
[
Cone [a=3.0; h=4.0 ( area=39.98594644342529; volume=113.09733552923255 )],
Cone [a=4.0; h=5.0 ( area=71.08612701053386; volume=335.1032163829112 )]
]
Hint #1 - the reqs say this: "Get the output for volumes and surface areas of cylinders and cones ...". So obviously you need API methods to calculate the volume and surface area of a shape, and you need test code to construct sample 3D shapes, and call the methods that calculate the volume.
Hint #2 - the reqs say this: "try to use toString() method". So obviously, you need to implement toString() on your classes.
Hint #3 - the reqs do not talk about rendering shapes, and you don't need the location of a shape to calculate its volume.
So, lets look at you error messages, they are quite clear saying what is wrong.
task.java:25: task.Cones is not abstract and does not override abstract method getVolumeCylinder() in task.GeometricShapes
public static class Cones extends ThreeDShapes
^
task.java:58: task.Cylinder is not abstract and does not override abstract method getVolumeCylinder() in task.GeometricShapes
public static class Cylinder extends ThreeDShapes
^
So, your interface GeometricShapes defines a method getVolumeCylinder(). (Why?)
This means, every (non-abstract) class implementing this interface needs to have this method, too (if not some superclass is already implementing this).
Why did you put these methods in the Interface? What does your GeometricShapes interface represent? A collection of shapes? A single shape (then the name should be in singular, not plural)?
Think about this first, then you'll get the answer about which methods are useful here, and how to structure your subclasses.
task.java:64: cannot find symbol
symbol : variable cylinderBase
location: class task.Cylinder
return cylinderBase * cylinderHeight;
^
This error message (and all the following ones) mention variables that are not declared anywhere. Think about where you are using these variables, and of what object they would be properties. Then declare them in this object, and organize giving the right values to them.
task.java:126: cannot find symbol
symbol : class Cylinders
location: class task
new Cylinders()
^
This last message complains because you are trying to create an object of class Cylinders, and there is no such class. (You have a class named Cylinder, though.)