I'm using a Processing library to build my project in Java. I use a function that returns me an object of type PShape (which I don't have access to source).
I need to make this object of type Shape (a class I designed that extends PShape).
How can I make that?
Basically I have:
PShape pShape = loadShape(filename);
Where loadShape is a function I don't have access to source code.
I want to somehow do:
class Shape extends PShape {...}
and then
Shape shape = (Shape) loadShape(filename);
But it won't work, once loadShape() will give me a PShape, not a Shape
How can I make loadShape returns a Shape?
Thank you
If loadShape() returns a PShape, then it returns a PShape. You can't make it return a subclass of PShape.
Easiest approach would be Shape either copies the PShape into a new instance:
e.g.
Shape myLoadShape(String filename)
{
return new Shape(loadShape(filename));
// Assumes you have a `Shape(PShape)` constructor.
}
or perhaps Shape isn't a subclass, but it contains a PShape data member.
class Shape
{
// No one picked up my C++ syntax goof ;-)
protected PShape pshape;
// Using a constructor is just one way to do it.
// A factory pattern may work or even just empty constructor and a
// load() method.
public Shape(String filename)
{
pshape = loadShape(filename);
// Add any Shape specific setup
}
}
Related
i started learning Java in university and we have an assignment that requires us to use a Superclass for Shape and Subclass that extend the shape.
This is the full questions:
Create a super class “Shape” from which you derive two subclasses “Square” and “Rectangle” with functions to calculate the square area and the rectangle area. In addition, to the function “toString” to display the square and rectangle info. Derive another sub class “Cube” from square with a function to calculate its area and a function “toString” to display the cube info."
What we need to do is calculate the shapes using the classes. Where should I start or move forward to solve the assignment?
This is where I think I should start, but need some guidance
public class Shapes {
class Shape {
}
class Rectangle extends Shape {
}
class Square extends Shape {
}
}
First, Shape class should be abstract, since you won't create any specific object of this class and you'll only use it as a "canvas".
This class has to have an abstract method, let's call it getArea(), that you'll have to override in your child classes to accomodate to the specified requirements for each kind of shape.
The toString() method belongs to Object class, since every class in Java extends from Object, you don't have to define anything, just override this method to return the desired String in every child class.
According to the definition you have post, the Cube class would be a composition of Square (a cube is composed by squares, but it's not a square), so I'd extend it from Shape and define it as a List or an array of 6 Square, so the getArea() of Cube would be the summatory of every Square area in it.
Putting aside the quality of the question:
You have a Shape class that will contain a method calculateSomething().
Shape does not define a specific shape so most likely you can return a -1 or 0?
Now, we can determine that the method of the Shape class does not provide us with any real value/info. Even if you create a Shape shape = new Shape() object and call its method, it does not help us at all.
Instead it provides us with a method that each subclass has to override in order to get the intended results.
What does that mean and how it works?
For you to not always have to do Rectangle rect = new Rectangle() for every single class and object, the Rectangle becomes a subclass of the Shape class.
This enables you to later do Shape rect = new Rectangle().
The big benefit of this is that you create an abstraction mechanism, meaning that you have a lot of shapes, either rectangles or triangles etc, but they all are Shape objects in the end.
So later you can just do:
Shape rect = new Rectangle();
Shape triangle = new Triangle();
rect.calculate();
triangle.calculate();
Instead of the more meticulous:
Rectangle rect = new Rectangle();
Triangle triangle = new Triangle();
rect.calculate();
triangle.calculate();
The former can further be utilised by:
// Putting all the objects in a list
List<Shape> shapes = new ArrayList<>();
// Create objects and add them
Shape rect = new Rectangle();
Shape triangle = new Triangle();
shapes.add(rect);
shapes.add(triangle);
As you can see for yourself, it is easier to handle and iterate over a list with all the elements being of type/class Shape.
// Basic example
for (Shape shape : shapes)
shape.calculateSomething();
Imagine if you had a hundred different shapes except Rectangle and Triangle. The latter method, without using inheritance, would quickly come to consume your project in an ever ending trial of maintenance and code changing.
By utilising inheritance otherwise, you can increase your Shape classes as much in quantity as you want and the same methods that used to work for a Shape, would still work for all the future new objects.
How does it work in practise? How do i create a subclass?
As you already know you can link your classes through the extend keyword.
But that is only the start.
To be able to utilize the inheritance, you will have to overwrite the method of your choosing, in the child class.
Take for instance the previous example:
Shape rect = new Rectangle();
rect.calculate();
But that raises the question, how can you get the correct value of calculate() method, when Shape class has a -1 or 0 returning from it and rect variable is now of type Shape?
Easily, you can override a method of the parent class through the #Override tag and by implementing the same method again on the child class but with different calculations. Example:
class Shape {
public void calculate() { return 0; }
}
class Rectangle extends Shape {
#Override
public void calculate() { return 2; }
}
Note that the name, variables etc of the method must be identical.
Now in the case of:
Shape rect = new Rectangle();
rect.calculate();
the calculate() method will return the number 2.
This happens because even though the rect object is of type Shape, it is also a Rectangle. Every Rectangle is a Shape. So when you try to call the desired method, the program knows to choose the overrided method of the Rectangle class, because in essence it is a Rectangle, covered by the abstraction Shape.
This works for any number of Shape subclasses, each with their own unique implementation of the method.
Also note that a Rectangle subclass can have its own private fields that are used in the other methods:
class Rectangle extends Shape {
private int height;
private int width;
// constructor
public Rectangle(int h, int w) {
this.height = h;
this.width = w;
}
#Override
public void calculate() {
return this.w * this.h;
}
}
So to answer your question, you just override the methods you want for each class as you desire. If a method is not overriden, then the original of the Shape parent class is run.
I hope this shined a little bit of light in your confusion towards abstraction and inheritance.
PS:
I know that you might be confused, but there are hundreds of answers and forums out there explaining this exact thing and that is how we all learned it. It needs time unfortunately but you will have a deeper understanding if you look at something yourself. I'm sure you have taken a taste of what is defined as 'wrong' or 'bad' to ask in here and that you will be more susceptible into studying it yourself in the future, considering there is material needed. I just tried to reach out to you because i have been in your place and believed i could make a difference with my approach.
If you have anything else to add or something to correct, it is always welcome in the comments section.
Edit:
As mentioned by the other guy that answered, the Shape class can and should be an abstract one. I just assumed you wanted it to be a normal one.
I have a question about polymorphism in Java. I have a abstract base class Shape and two derived classes Rectangle and Circle. I know that I can call overridden methods in Circle and Rectangle class with a Shape class reference but what if I have a method that Shape class doesn't have but Circle class has. How can I use polymorphism in this situation?
You cannot use polymorphism in this situation. The very idea of polymorphism is that you can use an object in a specified way irrespective of its actual shape (specific object type). By requiring access to a method that is unique to (literally) a specific shape, you must forego polymorphism.
(The above argument would not apply if Circle actually had subclasses, in which case you could polymorphically call these methods, but this is just moving the argument somewhere else.)
This happens all the time. The answer is that you need to cast your Shape to a Circle to access the method
Shape s = ...;
if (s instanceof Circle) {
((Circle)s).foo(); //method only on Circle
}
If you store a Circle in a Shape instance, you can invoke Circle methods on s by casting s to Circle:
Shape s = new Circle();
...
if ( s.instanceof(Circle) ) {
((Circle)s).circleMethod();
}
Apart from the casting solution suggested by other answers, if you think all subclasses of Shape should provide that method but you can't/don't want to implement it on Shape, you can declare the method as abstract and implement the method in Circle and Rectangle.
public abstract class Shape {
public abstract void foo();
}
public class Circle extends Shape {
public void foo() {
// Implementation
}
}
then you can do:
Shape s = new Circle();
s.foo();
I have a Point object that holds coordinates, I then use that Point in the creation of two other objects, a Triangle and a Circle, then inside circle object I translate that point. It also translates the point in the triangle class. Why is this? Have I just set up two variables to access the same object rather than have a 'copy' of that object in both shapes? How can I amend this?
I create the point in the main class then pass that point onto the constructors of both the Circle and Triangle classes which then assign it to a property of that class.
So it's like this:
//main class
Point p = new Point(50,50);
Circle c = new Circle(p);
Triangle t = new Triangle(p);
c.translate(20,30); //also translates the triangles point
//Circle class
public Circle(Point p) {
this.p = p;
}
//Triangle class
public Triangle(Point p) {
this.p = p;
}
Yes, you passed two references to the same Point object to Circle and Triangle.
To avoid this, there are basically two solutions:
create a copy of the Point object (either before passing it to Triangle and Circle, or in the constructor of those two classes, to make sure they use a different instances)
make the Point class immutable (all fields final, no setter), to make sure nobody can ever modify a Point. To translate a point, you would then be forced to create a new Point, with new coordinates. This is much safer, because you can't forget to make a copy. The immutability guarantees that the point can be shared between shapes without any way for them to modify each other by modifying their points.
The constructors for both your Circle and Triangle classes just assign the Point they are given to a data member. In this way, you're storing a reference to the same object, and every time it's manipulated, it will effect all references to it.
A safer way of handling such situations is, as you suggested, to copy the object passed to the constructor. E.g.:
//Circle class
public Circle(Point p) {
this.p = new Point(p.getX(), p.getY());
}
Alternatively, if you defined Point as clonable:
//Circle class
public Circle(Point p) {
this.p = p.clone();
}
Your making one instance of the Point object and making references to that one Point object in the Circle and Triangle object instances. The translate method modifies that Point object.
I have a Shape superclass and a NestedShape subclass. The NestedShape subclass has an ArrayList ('ShapesList') of Shapes that are nested within it. I need to implement a 'contains' method for NestedShape. This method, when given a Shape object, should check whether the shape exists in the NestedShape's ShapeList. My implementation at the moment is very simple: just call the ArrayList .contains() method on ShapesList.
However, the 'contains' method I need to implement also has to check that for any NestedShape in the ShapesList, that shape's ShapeList also doesn't contain the shape that is being searched for. The obvious way to me of doing this is to use instanceof to check if each Shape in the ShapeList is a NestedShape. Then, I guess I'd recursively call my 'contains' method on it if it was a NestedShape. However, I'm not sure if this is a good way of doing this - I've heard that the use of instanceof is frowned upon (also, I'm not sure if my idea of using recursion would even work).
Could anyone suggest a better way of solving this problem?
Thanks :)
Use polymorphism:
public class Shape {
public boolean contains(Shape shape) {
return false;
}
}
public class NestedShape extends Shape {
private List<Shape> subShapes = new ArrayList<Shape>();
#Override
public boolean contains(Shape shape) {
if (subShapes.contains(shape)) {
return true;
}
for (Shape subShape : subShapes) {
if (subShape.contains(shape)) {
return true;
}
}
return false;
}
}
Two ideas:
Don't let NestedShape extend Shape, but handle them seperately.
Let all Shapes be 'nested'. With single shapes returning always false for contains().
If
the performance of the contains() method is your concern and
NestedShape are immutable meaning the list of nested Shape instances once set will never change
then I would suggest a slightly different approach.
Instead of recursively iterating though all the NestedShapes you can add a Set inside the Shape class that will store the references to all the NestedShape instances for which it is possible to access this Shape instance.
I have a class called Shape that is abstract, and a class named Circle that extends Shape
Shape shapeCircle = new Circle();
I can set and get colors of shapeCircle fine because the color getters and setters are in Shape , but the dimensions of Circle is only for the Circle class (radius).
If Circle class has an instance variable private int radius and a method called getRadius(), how can I get/set the radius of shapeCircle? I tried shapeCircle.getRadius();, but no luck.
Only methods of Shape are accessible with object shapeCircle.
shapeCircle is type Shape, methods in Circle are not visible.
By using this,
Circle shapeCircle = new Circle();
you can call both method of Circle and Shape. The above case is take advantage of only Inheritance.
Edit
But if you add public abstract int getDimension(); in Shape class and Circle class implements getDimension() method
#Override
public int getDimension() {
return radius;
}
All classes that extends Shape needs to implements getDimension() method. But each subclass has its own dimension.
You can use
Shape shapeCircle = new Circle();
shapeCircle.getDimension();
This takes advantage of both polymorphism and abstract class.
Shape shapeCircle = new Circle();
Here the reference is of Shape and shape class doesn't defines radius variable.So you cannot use shapeCircle.getRadius();
To invoke get/set radious method type cast the shapecircle variable like this
Circle shapeCircle = (Circle)shapeCircle;
Now you can invoke the get/set radious methods. Please note that typecasting code should be in some different method to benefit using polymorphism.
EDIT:
You should design your abstract classes or interfaces to be having all important/common operations/methods which will help you in writing polymorphic code. For example: Radius field is specific to a Circle class.But consider you eventually want to calculate the area. So you should define CalculateArea() method in your abstract class and let every shape implement this method.This way, you achieve polymorphism.
Shape ShapeCicle = new Circle(Radius);
Float area = ShapeCircle.area();
Point is don't confine yourself with the radius example.Try to define classes in a way so that you can benefit from polymorphism.
You have to use instanceof keyword to check for the original type here . If the type is Circle, then you can type cast and call the getRadius method. Something like
if (shapeCircle instanceof Circle) {
Circle circle = (Circle)shapeCircle;
int radius = circle.getRadius();
}
That should do.
'Shape is not Circle' = Circle methods not available for Shape.