I'm practicing inheritance in Java and got stuck on getter method in subclass.
Here is the Point class:
package OOP.LinePoint;
public class Point {
private int x;
private int y;
public Point(int x, int y){
this.x = x;
this.y = y;
}
public String toString() {
return "Point: (" + x + "," + y + ")";
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
Here LineSub class:
package OOP.LinePoint;
public class LineSub extends Point{
Point end;
public LineSub(int beginX, int beginY, int endX, int endY){
super(beginX, beginY);
this.end = new Point(endX, endY);
}
public LineSub(Point begin, Point end){
super(begin.getX(),begin.getY());
this.end = end;
}
#Override
public String toString() {
return "LineSub [begin=" + "(" + super.getX() +"," + super.getY() +") " + "end=" + end + "]";
}
public Point getEnd() {
return end;
}
public void setEnd(Point end) {
this.end = end;
}
public Point getBegin(){
}
public void setBegin(Point begin){
setX(begin.getX());
setY(begin.getY());
}
}
My problem:
1) toString() method. I'm trying to print two points(begin and end). As you can see end is easy but begin Point is inherited and idk what should I type. The way I'm getting x and y of point is working but for me it seems to be lame way of doing that. For sure there is a better way, could you please help me with that?
2) Point getBegin() method. I've tried:
public Point getBegin(){
return (Point)this;
}//Not working(getting whole Point object)
and
public Point getBegin(){
return new Point(getX(), getY());
}//Very noob way
I have no other ideas, please lend me your wisdom.
IMHO, it is not a good use of inheritance. Your case is not a valid candidate for Inheritance.
A class is a good candidate for inheritance only when it conforms to is-A relationship.
A Line is not a Point but it a collection of points (In your case it is being and end).
So, It is a good candidate for composition (Has-A).
A line HAS a begin and an end point. You are using both inheritance (For begin point) and composition (For end point) for code reuse.
Adhere to composition and have two points (begin and end) in Line class.
To get the start Point you must cast yourself to a Point. You can call your super.toString to access the toString of the parent class.
#Override
public String toString() {
return "LineSub [begin=" + super.toString() + "end=" + end.toString() + "]";
}
public Point getBegin() {
return (Point) this;
}
The fact that you have to cast is an indicator that you have your hierarchy wrong. This structure would normal be implemented using two points.
public class LineSub {
Point begin;
Point end;
Related
I'm trying to add a method an an array like this.
Position[] positions = new Position[10];
Position pos = positions.getPosAt(x, y);
I know this can be accomplished like:
Position pos = getPosAt(positions, x, y)
But I would like to know if there is a way to accomplish the first method.
you can make a class handler for this, like this PositionArray class (name it as you would like):
public class Test {
public static void main(String... args) {
Position[] positions = new Position[10];
positions[0] = new Position(5, 10);
positions[1] = new Position(11, 18);
positions[2] = new Position(20, 7);
PositionArray pa = new PositionArray(positions);
System.out.println(pa.getPosAt(5, 10)); // Position{x=5, y=10}
}
}
class PositionArray {
private Position[] positions;
public PositionArray(Position[] positions) {
this.positions = positions;
}
public Position getPosAt(int x, int y) {
for (Position p : positions) {
if (!Objects.isNull(p)) {
System.out.println(p.getX() + " " + p.getY());
if (p.getX() == x && p.getY() == y) {
return p;
}
}
}
return null;
}
}
class Position {
private final int x;
private final int y;
public Position(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
#Override
public String toString() {
return "Position{" + "x=" + x + ", y=" + y + '}';
}
}
There is no way to do this in Java. You could possibly create your own class that contained an array of Position objects and provides e.g. get methods, but there is no way whatsoever to add methods to classes you do not control, including all array types.
I've got an ArrayList filled with 500 Point-Objects. There might be duplicates in it so I want to find them and if needed delete them except for one. The plan is: Check for each Point in the arrayList, if there is an equal Point, if so, add it to a List, after the test for each Point, delete all Points from the original List that are also in the toRemove-List.
But here comes the Problem: If i run this, its going for an endless loop. Do I have a serious thinking error? I think it might be a really simple misstake but I cant think about it
Also, if you have any proposal on how to do this better, let me know.
This is my method:
private void checkForDuplicates() {
ArrayList <Point> toRemove=new ArrayList<Point>();
int i=0;
while(i<points.size()) {
Point local=points.get(i);
for (Point p: points) {
if (local!=p && local.equals(p)) {
toRemove.add(p);
}
}
for (Point p: toRemove) {
points.remove(p);
}
i++;
}
}
Update:
Something is really broken. It looks like the method might work right now, but my programm isnt. The code isnt running anymore if I call this method somewhere. I cant even print out something on the console as the first line in my main method while i call checkForDuplicates() somewhere else?!
Point:
public class Point {
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
#Override
public boolean equals(Object p) {
if (this == p) {
return true;
}
if (!(p instanceof Point)) {
return false;
}
Point point = (Point) p;
return this.getX() == point.getX() && this.getY() == point.getY();
}
}
I recommend using streams for this task:
List result =
points
.stream()
.distinct()
.collect(Collectors.toCollection(ArrayList::new));
To make distinct() work as expected, you will probably have to define an equals()method for your Point class.
User Frank Puffer has answered the question in Java 8. It seems as if you're in older version of Java, so the following might help you. It just creates a Set object and copies the ArrayList to it. Because the Set will remove the duplicates automatically you don't need to make the code much more complexer than it should be, and is less error prone.
private void removeDuplicates() {
Set<Point> distinctPoints = new HashSet<>();
for (Point p : points) {
distinctPoints.add(p);
}
points = new ArrayList<String>(distinctPoints);
}
And include the following method impl to the Point class so that Point objects can be searched in the Set:
#Override
public int hashCode() {
int hashValue = 11;
hashValue = 31 * hashValue + x;
hashValue = 31 * hashValue + y;
return hashValue;
}
#Override
public String toString() {
return "Point[" + X + ", " + Y + "]";
}
The toString() method is a nice to have feature.
We got the following exercice in our last exam, and I don't understand the right answers except the 1st one.
Here is it:
public class Gran {
private int x;
public Gran() { this.x = 68; }
public int age() { this.x = this.x+1; return this.x; }
#Override
public String toString() { return "Gran " + age(); }
}
public class Dad extends Gran {
private int x;
public Dad() { this.x = 41; }
#Override
public String toString() { return "Dad " + age(); }
}
public class Bro extends Dad {
private int x;
public Bro() { this.x = 21; }
#Override
public int age() { System.out.print("Bro "); return x; }
}
public class Sis extends Dad {
private int x;
public Sis() { this.x = 17; }
#Override
public int age() { System.out.print("Sis "); return super.age() - x; }
#Override
public String toString() { return "Sis " + super.toString(); }
}
What would be the correct print-outs if we call this:
Gran[] family = new Gran[] {new Gran(), new Dad(), new Bro(), new Sis()};
for (Gran member : family) System.out.println(member.toString());
It would be really helpful for me, if you tell me the logic behind the right answers.. I got really confused when I checked them!
You should check out the spec.
Especially Example 8.4.8.1-1. Overriding:
class Point {
int x = 0, y = 0;
void move(int dx, int dy) { x += dx; y += dy; }
}
class SlowPoint extends Point {
int xLimit, yLimit;
void move(int dx, int dy) {
super.move(limit(dx, xLimit), limit(dy, yLimit));
}
static int limit(int d, int limit) {
return d > limit ? limit : d < -limit ? -limit : d;
}
}
The caption says:
Here, the class SlowPoint overrides the declarations of method move of class Point with its own move method, which limits the distance that the point can move on each invocation of the method. When the move method is invoked for an instance of class SlowPoint, the overriding definition in class SlowPoint will always be called, even if the reference to the SlowPoint object is taken from a variable whose type is Point.
So with that in consideration, lets look at your example.
The hierarchy is:
Dad is a Gran
Bro is a Dad
Sis is a Dad
The declared type of all of the objects is Gran because of the line Gran[] family = new Gran[] {new Gran(), new Dad(), new Bro(), new Sis()}; That is the same as saying that the reference to each of the objects in the array are taken from a variable whose type is Gran.
Now you will call toString() on each of the elements in the family array. The first is Gran.toString(). When that object was created its x variable was initialized to 68. So the Gran.toString() method will build a String that is first "Gran" then call the age() method which increments x by one then returns the value of x which is 69 at this point. The + operator implicitly creates a new String that coerces the int to a String giving a String "Gran 69".
Next Dad.toString is very similar to Gran. Notice that it starts with the String "Dad" then calls age() which is inherited from Gran. So the output should be "Dad 69". The trick here is that the x variable is private scope, so the x in Dad is a different x then in Gran. That is the same for all of the classes.
For Bro, this class is a Dad, and Dad is a Gran. There is no overridden toString here so Dad.toString() gets used. That makes a String "Dad" then calls Bro.age() this prints "Bro" then returns the x from Bro to create a new String "Dad 21". The line is will look like "Bro Dad 21" because the print of "Bro" happens before the print of "Dad 21".
As for Sis this one is the toughest one. You should take everything from above and convince your self of how Overriding and scoping works. Good luck! I hope this helps.
The following is a toy problem of my original problem. Bird is an interface. Cardinal is the subclass of Point and it implements the Bird interface. The Aviary class carries out the implementation.
Question: What should I put in the getPosition() instance method such that the Aviary class carries the getPosition() method correctly?
Please correct me if the abstract method in the bird interface is coded wrong.
public interface Bird{
public Point getPosition();
}
public class Point{
private int x;
private int y;
// Constructs a new Point at the given initial x/y position.
public Point(int x, int y){
this.x = x;
this.y = y;
}
// Returns the x-coordinate of this point
public int getX(){
return x;
}
// Returns the y-coordinate of this Point
public int getY(){
return y;
}
}
Question is in the following code:
public class Cardinal extends Point implements Bird{
// Constructors
public Cardinal(int x , int y){
this(x,y);
}
// not sure how to write this instance method
public Point getPosition(){
???????????
}
}
public class Aviary{
public static void main(String[] args){
Bird bird1 = new Cardinal(3,8);
Point pos = bird1.getPosition();
System.out.println("X: " + pos.getX() + ", Y: " + pos.getY() );
}
}
Just return the object itself:
public Point getPosition(){
return this; // returns a Point object
}
I gave an answer, but I am not sure if you have a design nightmare or a one-of-a-kind design simplification. A Point subclass implementing a Bird makes me bang my head on the wall, but having both types in one object will make the calculations pretty neat, (if you have massive calculations, that is). Because instead of bird.getPosition().getX(), you can write bird.getX().
Point bird1 = new Cardinal(3, 8);
Point bird2 = new Cardinal(4, 12);
// calculate the distance between two birds
double distance = Math.sqrt(Math.pow(bird2.getX() - bird1.getX(), 2) + Math.pow(bird2.getY() - bird2.getY(), 2));
But if your system is not a bird simulator that needs heavy calculations on birds represented by mere Point objects, I think you should use composition over inheritance.
public interface IBird {
public Point getPosition()
}
class Bird implements IBird {
private Point position;
public Bird(int x, int y) {
this.position = new Point(x, y);
}
public Point getPosition() {
return this.position;
}
}
// and then in main()
Bird bird = new Bird(3, 8);
Point pos = bird.getPosition();
System.out.println("X: " + pos.getX() + ", Y: " + pos.getY() );
The Cardinal class objects have an is-a relationship with the Point class objects, so you could just return this; as Krumia suggested.
P.S. you can use the super keyword when referring to a superclass within a subclass to access it's protected and public methods.
I am learning java and trying to execute a simple script. I have a class Point as the following:
package user_package;
public class Point {
float x;
float y;
float z;
public Point(float x, float y, float z){
this.x = x;
this.y = y;
this.z = z;
}
public static Point add(Point p1, Point p2){
return new Point(p1.x + p2.x, p1.y + p2.y, p1.z + p2.z);
}
}
Then I have the main file like this:
import user_package.Point;
import static user_package.Point.add;
class Tutorial{
public static void main(String[] args){
float x1 = 1, y1 = 1, z1 = 1;
float x2 = 2, y2 = 2, z2 = 2;
Point p1 = new Point(x1, y1, z1);
Point p2 = new Point(x2, y2, z2);
Point p3 = add(p1, p2);
System.out.println(p3);
}
}
I do this in Netbeans. It gives me no errors and the build is successful but the output is:
user_package.Point#68e26d2e
I tried to search myself but nothing found. Please tell me what the problem is and how I can solve it.
You have not overridden toString method for Point class so the Object class toString method is called. If you want meaningful textual representation of your object, override toString
public String toString(){
return "stringYouWantToReturn";
}
In your case, add this to Point class
public String toString() {
return "Point [x=" + x + ", y=" + y + ", z=" + z + "]";
}
When you print an object using println method, toString() is implicitly called.
When you write
System.out.println(p3);
There toString() calls on the Object you passed.
Since you didn't provide any implementation there,
You have to ovveride the toString() method in your Point class.
As per docs of toString()
Returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object.
So
user_package.Point#68e26d2e is the textual representation of Point class.
To get the required output, write the logic in overridden toString method in Object class and return the string there.
package user_package;
public class Point {
float x;
float y;
float z;
public Point(float x, float y, float z){
this.x = x;
this.y = y;
this.z = z;
}
public static Point add(Point p1, Point p2){
return new Point(p1.x + p2.x, p1.y + p2.y, p1.z + p2.z);
}
#Override
public String toString() {
StringBuilder result = new StringBuilder();
result.append(this.x).append(",");
result.append(this.y).append(",");
result.append(this.z)
return result.toString();
}
}
You're printing object of class Point. If println() method doesn't know how to print a class, it prints its name. That's why you get such result.
You can do it either like this:
System.out.println(p3.x + ", " + p3.y + ", " + p3.z);
Or as SURESH ATTA suggested, by overriding toString() method for your Point class (or in other words - learning your Point class to know how to behave when you want to print it).
You need to override toString() function in Point class or create user defined function in Point class.
Using toString() method
public class Point {
public String toString()
{
//your code goes here
return "Point "+ "X : "+ x +"Y : "+ y + "Z : "+z;
}
}
As the previous answers already implicitly stated
System.out.println(p3);
actually is
System.out.println(p3.toString());
and since you are not providing an own implementation for the toString() method. The default implementation of Object is called. Which results in your given output. In order to change that behaviour you have to override toString()
#Override
public String toString() {
return "Point: x=" + x + ", y=" + y + ", z=" + z;
}