How to interpret and use a class given an interface object? - java

I have an interface. One of my methods takes as argument an object of this interface. Depending on the concrete class, I want to build a different object.
public interface Shape {
public void draw();
}
public class Circle implements Shape {
private int radius;
//constructor etc.
public void draw() {
System.out.println("CIRCLE!");
}
public int getRadius() {
return radius;
}
}
public class Square implements Shape {
private int side;
//constructor etc.
public void draw() {
System.out.println("SQUARE!");
}
public int getSide() {
return side;
}
}
public class MyClass {
public void myJob(Shape shape) {
if (shape.getClass().toString().equals("Circle")) {
// some missing code...what to do here? type cast? transform?
int radius = shape.getRadius();
}
}
}
How do I take the Shape interface and then get the radius or side out of it depending on the type of class?

First, there is no need to use reflection for this, you can use the keyword instanceof
public void myJob(Shape shape) {
if (shape instanceof Circle) {
// some missing code...what to do here? type cast? transform?
int radius = shape.getRadius();
}
}
Then, what you want to do is to cast your shape into a circle, so you can treat it like a circle:
public void myJob(Shape shape) {
if (shape instanceof Circle) {
Circle circle = (Circle) shape;
// Some Circle job
int radius = circle.getRadius();
}
}
Finally, if as you said you want to apply different treatments to different implementations of Shape, you can explicitly type the parameter:
public void myJob(Circle circle) {
// Some Circle job
}
public void myJob(Square square) {
// Some Square job
}
However, a better way to do that would be to use the Shape interface:
public interface Shape {
void draw();
void myJob();
}
public class MyClass {
public void myJob(Shape shape) {
shape.myJob();
}
}
}

All of the code that is Shape specific should be located in the methods overridden by each subclass.
public interface Shape {
public void draw();
public int getMeasure();
}
public class Circle implements Shape { ... } // The code for the methods in Shape should be written here.
public class Square implements Shape { ... }
public class MyClass {
public void doWork(Shape shape) {
int measure = shape.getMeasure();
}
}
Typically, looking up the class by name at runtime is an unnecessary hassle that can be avoided.
Edited for the question.

You can check if it's an instance of Circle by using instanceof and then cast it to a Circle if so.
if (shape instanceof Circle) {
Circle circle = (Circle)shape;
int radius = circle.getRadius();
}

Related

How to call both abstract methods AND interface methods in an array?

I created an array to hold different shapes. Circle and Square are abstract classes extended from Class Shape. Cube and Sphere are from the interface called ThreeDShape. I need to find the area for all shapes and the area and volume for the 3D shapes and call them using an array. I got the Test class to be able to use the abstract methods. How do I get the test class to use the interface methods? How do I print the abstract methods AND the interface methods in a single array?
I also need to call the details of each class from within the array using the getClass() method.
public class Test {
public static void main(String[] args) {
Shape [] shape = new Shape[4];
Circle circle = new Circle();
shape[0] = circle;
Shape sphere = new Sphere();
shape[1] = sphere;
Shape cube = new Cube();
shape[2] = cube;
Square square = new Square();
shape[3] = square;
for(Shape shape1 : shape) {
System.out.println("The area of " + shape1.getClass() +" is " + shape1.area());
System.out.println("The volume of " + shape1.getClass() +" is " + shape1.volume());
System.out.println("Found in " + shape1.getClass());
System.out.println(" ");
}
}
}
public interface ThreeDShape {
public abstract double volume();
}
public class Cube implements ThreeDShape{
double a = 5;
public double volume() {
return a*a*a;
}
public double area() {
return 6*a*a;
}
}
public class Square extends Shape {
double s = 5;
public double area() {
return s*s;
}
}
public class Circle extends Shape {
double r = 9;
public double area() {
return r*r*3.14;
}
}
public class Sphere implements ThreeDShape {
double r1 = 5;
public double volume() {
return ( 4.0 / 3.0 ) * Math.PI * Math.pow( r1, 3 );
}
public double area() {
return 4*3.14*r1*r1;
}
}
public abstract class Shape {
public abstract double area();
protected abstract double volume();
}
```
Your design is wrong.
Everything should be a subclass of Shape. If you want some specialization then Sphere and Cube should be subclasses of ThreeDShape that is subclass of Shape. So to do what you do you just call a super method of Shape that has different implementation (aka is overwritten) on every subclass.
The loops becomes just this:
for (Shape s: shapes){
s.myBeautifulMethod();
}
If you want to keep ThreeDShape as an interface then Sphere and Cube should be both Shape and ThreeDShape:
public class Sphere extends Shape implements ThreeDShape { [...] }
public class Cube extends Shape implements ThreeDShape { [...]}
but I would stick with a single hierarchy, since otherwiese you are moving forward to multiple inheritance, and this is not very Java.
You are asking for a reflective logic where is not needed at all.
Hope I helped.
If you want to do this, you need to check the type of each shape and cast as you loop through the array. Something like:
for(Shape shape1: shape) {
System.out.println("Area: " + shape1.area());
if(shape1 instanceof ThreeDShape) {
System.out.println("Volume: " + ((ThreeDShape) shape1).volume());
}
}
Generally, type checking and casting like this should be avoided - it probably indicates bad program design. Interfaces and abstract classes are designed for situations where you have multiple types that support the same API. Here, though, you have 2 different APIs: Shape and ThreeDShape.
What I prefer is to avoid instanceOf, getClass and so on
public interface OperationalShape {
double getVolume();
double getArea();
String getName();
boolean supportsVolume();
}
public class Circle implements OperationalShape {
public double getVolume() {
throw new CustomUnsupportedException();
{
public boolean getArea() {
return ...
}
public String getName() {
return "Circle";
}
public boolean supportsVolume() {
return false;
}
}
After that you can iterate on your collection of OperationalShapes, checking with an if(supportsVolume()) if you should call getVolume() or not. You can get the name via getName().
For this code to compile ,
1)You need to change the Shape class to Shape interface. because interface can only implement an interface and not class.
or
2)Change ThreeDShape to class and extends to Shape class
ThreeDShape sphere = new Sphere();
shape[1] = sphere;
1 type implementation
public class Test {
public static void main(String[] args) {
Shape [] shape = new Shape[4];
Circle circle = new Circle();
shape[0] = circle;
ThreeDShape sphere = new Sphere();
shape[1] = sphere;
ThreeDShape cube = new Cube();
cube.volume();
shape[2] = (Shape) cube;
Square square = new Square();
shape[3] = square;
int x = 3;
int z = 1;
for(Shape shape1 : shape) {
System.out.println("The area of the circle is " + shape1.area());
System.out.println("The volume of the circle is " + shape1.volume());
x++;
z++;
System.out.println("Found in " + shape1.getClass());
System.out.println(" ");
}
}
}
interface ThreeDShape extends Shape{
public abstract double volume();
}
class Cube implements ThreeDShape{
double a = 5;
public double volume() {
return a*a*a;
}
public double area() {
return 6*a*a;
}
}
class Square implements Shape {
double s = 5;
public double area() {
return s*s;
}
#Override
public double volume() {
// TODO Auto-generated method stub
return 0;
}
}
class Circle implements Shape {
double r = 9;
public double area() {
return r*r*3.14;
}
#Override
public double volume() {
// TODO Auto-generated method stub
return 0;
}
}
class Sphere implements ThreeDShape {
double r1 = 5;
public double volume() {
return ( 4.0 / 3.0 ) * Math.PI * Math.pow( r1, 3 );
}
public double area() {
return 4*3.14*r1*r1;
}
}
interface Shape{
double area();
double volume();
}
As the other answers mentioned, the design is wrong. This is how I would do it.
If you have to use interface and abstract class in one project, you need to think which of them is more generic. In this class, is Shape or ThreeDShape more generic? Ofcourse, ThreeDShape is a kind of Shape.
Hence, Shape should be an interface and ThreeDShape an abstract class that implements the Shape interface, and not the other way around. An abstract class can implement an interface without actually implementing its methods, but an interface cannot extend an abstract class.
public interface Shape {...}
public abstract class ThreeDShape implements Shape {...}
public class Circle implements Shape {...} // Same for Square
public class Cube extends ThreeDShape {...} // Same for Sphere

What is the purpose of using interface when its methods don't have any implementation we have to override them every time?

interface Interface {
void m1();
}
class Child implements Interface {
public void m1() {
System.out.println("Child.....");
}
}
public class InterfaceDemo {
public static void main(String[] args) {
Child c = new Child();
c.m1();
Interface i = new Child();
i.m1();
}
}
This is useful when you have several classes implementing same interface. It allows to use polymorphism. You can also use abstract classes to implement some common functionality. And starting Java 8 you can provide default implementation in interfaces themselves.
interface Shape {
void draw();
double getSquare();
}
class Circle implements Shape {
public void draw() {}
public double getSquare() {return 4 * PI * r * r;}
}
class Square implements Shape {
public void draw() {}
public double getSquare() {return w * w;}
}
class Main {
public static void main(String[] args) {
for (Shape s : Arrays.asList(new Circle(), new Square(), new Square(), new Circle())) {
s.draw(); //draw a shape. In this case it doesn't matter what exact shapes are in collection since it is possible to call interface method
}
}
}

Avoiding the need to cast in java inheritance

Lets say I had a simple inheritance structure like so:
class Shape {
int id;
}
class Circle extends Shape {
int radius;
}
class Square extends Shape {
int length;
}
class ToyBox {
List<Shape> shapes;
}
These objects cannot be augmented in any way (no adding methods/fields/accessors.change the file in any way) and should be treated as immutable/final. I have to return each of these shape objects to another part of the system I am working within with some extra information to go alongside each item. For example:
class extended Shape {
int id;
}
class ExtendedCircle extends ExtendedShape {
public Circle circle;
public Blah circleStuff;
public ExtendedCircle(Circle circle) {...}
}
class ExtendedSquare extends ExtendedShape {
public Square square;
public Blah squareStuff;
public ExtendedSquare(Square square) {...}
}
The only way I can think of accomplishing this task given a ToyBox of shapes is to iterate through the shapes list, do an instance of check and do a cast to circle, square etc. to then construct each of the corresponding "Extended" objects. This makes me a little uncomfortable so i am wondering if there is another way to design such a system?
If you need to avoid casting and using instanceof operator you probably would like to consider using Vistor design pattern. Applying it to your example if might looks as following:
class Shape {
int id;
public void visitingShape(ToyBox box) {
box.visitingShape(this);
}
}
class Circle extends Shape {
int radius;
public void visitingShape(ToyBox box) {
box.visitingCircle(this);
}
}
class Square extends Shape {
int length;
public void visitingShape(ToyBox box) {
box.visitingSquare(this);
}
}
class ToyBox {
List<Shape> shapes;
public visitingShape(Shape shape) {
// Do logic related to the shape
}
public visitingCircle(Circle shape) {
// Do logic related to the circle
}
public visitingSquare(Square shape) {
// Do logic related to the square
}
}
I can propose an approach which is closer to pattern-matching. It doesn't solve the problem using inheritance, but it should give the same advantages as a visitor pattern without the heavyweight aspect of it.
Simply introduce a ShapeType enumeration, make each shape return its type and use a switch-case structure to implement your logic. Might be more readable.
It seems like you're in a pretty tough spot not owning the shape classes but I think you could add shape proxies. It adds an additional layer but provides the ability to extend the shapes as well as additional control over the interface if you'd need it.
Let's say, given a Shape as follows:
public class Shape {
public void doSomethingWithShape() {}
}
You provide a ShapeProxy like so (implementing the Shape interface and providing a proxy into it):
public class ShapeProxy extends Shape implements IShapeProxy {
// Optional
#Override
public void doSomethingWithShape() {
// Do something extra if needed.
}
// From IShapeProxy
#Override
public ExtendedShape getExtended() {
return new ExtendedShape(this);
}
}
Likewise, you would have proxies for each additional shape:
public class CircleProxy extends Circle implements IShapeProxy {
#Override
public ExtendedCircle getExtended() {
return new ExtendedCircle(this);
}
}
And, of course, you could use it like this:
public static void main(String[] args) {
List<IShapeProxy> shapes = new ArrayList<>();
shapes.add(new ShapeProxy());
shapes.add(new CircleProxy());
shapes.add(new SquareProxy());
List<ExtendedShape> extendedShapes = new ArrayList<>();
shapes.forEach(s -> extendedShapes.add(s.getExtended()));
}
I would prefer it this way but if you couldn't change the type of List then you could still shove them in as Shapes and cast to get the extended type. Still, it's a common cast that wouldn't require knowledge about the type of shape at hand.
If that seems like too much or if you'd like to separate the extending from the proxy, you can combine the proxy idea with Dici's suggestion and add a type like so (changes to the interface not shown):
public enum ShapeType {
SHAPE, CIRCLE, SQUARE
}
public class CircleProxy extends Circle implements IShapeProxy {
// From IShapeProxy
#Override
public ShapeType getType() {
return ShapeType.CIRCLE;
}
}
// And...
for (IShapeProxy proxy : shapes) {
switch (proxy.getType()) {
case SHAPE:
// Build the extended type.
break;
...
}
}
}

Is there any benefits of using generic parameter rather than using the base class parameter?

Please review the code below:
abstract class Shape {
protected double x;
protected double y;
public Shape(double x, double y) {
this.x = x;
this.y = y;
}
abstract protected void draw();
}
class Circle extends Shape {
public Circle(double x, double y, double r) {
super(x, y);
this.r = r;
}
protected double r;
protected void draw() {
System.out.println(String.format("Draw Circle. %f %f %f", x, y ,r));
}
}
class RenderEngine {
public static void draw1(Shape s) {
s.draw();
}
public static <T extends Shape> void draw2(T t) {
t.draw();
}
}
public class Runner {
#Test
public void run() {
Circle c = new Circle(1,2,3);
RenderEngine.draw1(c);
RenderEngine.draw2(c);
}
}
What's the difference between draw1() and draw2()? Which one is better? Does draw2() have more extensibility? Or does draw2() have better performance?
There is no difference in your scenario, because the type of the object being drawn is consumed internally in the drawX method.
It would make a difference if your method were to use T in some other context, such as returning the original back to the caller:
public static <T extends Shape> T draw2(T t) {
t.draw();
return t;
}
This makes a difference in situations when a subclass defines new methods on top of the base class. For example, if Circle defined
double radius() { return r;}
you could do the following:
double r = RenderEngine.draw1(c).radius();
This would be impossible with an implementation returning Shape.
Note: The above is to demonstrate the differences, not to suggest that the new implementation is more desirable than the original one.
draw2 will do the same thing as draw for things that are already shapes. But when it says T extends Shape, it allows it to take in a parameter that is not a shape. At that point, it will allow it to use the draw method without crashing, whether or not it's a shape, it just might not draw anything.

How to execute method on object of Class<?>

I wonder is it possible to execute method from class on runtime on object of Class?
At first: I have method that returns me a class:
public static Class<?> getClassById(Long id) throws ClassNotFoundException {
if(d.id == 1L) {
return First.class;
} else if(d.id ==2L) {
return Second.class;
} else if(d.id ==3L) {
return Third.class;
} else {
throw new ClassNotFoundException();
}
}
Second: The way I execute it:
Index.GetClassById(1) which should return me Class. Now I would like to execute method myMethod() from that class. By the way, each class of (First, Second, Third) have this myMethod() method.
Please help.
A Class object is an instance of the type representing your class. This means that First.class.equals(new First()) will always return false.
What you want is to create an object based on your class and on that class call your method myMethod(), assuming that you classes (First, Second, Third) have a default constructor:
Class clazz = Index.getClassById(1);
First first = (First)clazz.newInstance();
first.myMethod();
The drawback on this approach is that you have to cast the object explecitly.
For this to relay work neatly you should define an interface that defines myMethod():
public interface MyInterface {
void myMethod();
}
public class First implements MyInterface {
...
}
public class Second implements MyInterface {
...
}
public class Third implements MyInterface {
...
}
Then you can define your method from above as:
public static Class<MyInterface> getClassById(Long id) throws ClassNotFoundException {
if(d.id == 1L) {
return First.class;
} else if(d.id ==2L) {
return Second.class;
} else if(d.id ==3L) {
return Third.class;
} else {
throw new ClassNotFoundException();
}
}
And call it like this:
Class<MyInterface> clazz = Index.getClassById(1);
MyInterface instance = clazz.newInstance();
instance.myMethod();
Since you have a class instance, you can get it's object instance and then invoke it's method by method's name:
//empty patameters array, to specify the method signature
Class noparams[] = {};
//get the class
Class cls = getClassById(1L);
//get an instance of the class
Object obj = cls.newInstance();
//get some method of the class by it's signatute (name and input parameters)
Method method = cls.getDeclaredMethod("myMethod", noparams);
//invoke this method without parameters
method.invoke(obj, null);
But the solution with some common interface is preferable, then you can get an instance of this interface and call it in usual way.
The problem that you talk about is a design pattern called abstract design pattern in which all your classes.
Step 1
Create an interface for Shapes.
Shape.java
public interface Shape {
void draw();
}
Step 2
Create concrete classes implementing the same interface.
Rectangle.java
public class Rectangle implements Shape {
#Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
Square.java
public class Square implements Shape {
#Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
Circle.java
public class Circle implements Shape {
#Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
Step 3
Create an interface for Colors.
Color.java
public interface Color {
void fill();
}
Step4
Create concrete classes implementing the same interface.
Red.java
public class Red implements Color {
#Override
public void fill() {
System.out.println("Inside Red::fill() method.");
}
}
Green.java
public class Green implements Color {
#Override
public void fill() {
System.out.println("Inside Green::fill() method.");
}
}
Blue.java
public class Blue implements Color {
#Override
public void fill() {
System.out.println("Inside Blue::fill() method.");
}
}
Step 5
Create an Abstract class to get factories for Color and Shape Objects.
AbstractFactory.java
public abstract class AbstractFactory {
abstract Color getColor(String color);
abstract Shape getShape(String shape) ;
}
Step 6
Create Factory classes extending AbstractFactory to generate object of concrete class based on given information.
ShapeFactory.java
public class ShapeFactory extends AbstractFactory {
#Override
public Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();
}else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
}else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}
#Override
Color getColor(String color) {
return null;
}
}
ColorFactory.java
public class ColorFactory extends AbstractFactory {
#Override
public Shape getShape(String shapeType){
return null;
}
#Override
Color getColor(String color) {
if(color == null){
return null;
}
if(color.equalsIgnoreCase("RED")){
return new Red();
}else if(color.equalsIgnoreCase("GREEN")){
return new Green();
}else if(color.equalsIgnoreCase("BLUE")){
return new Blue();
}
return null;
}
}
Step 7
Create a Factory generator/producer class to get factories by passing an information such as Shape or Color
FactoryProducer.java
public class FactoryProducer {
public static AbstractFactory getFactory(String choice){
if(choice.equalsIgnoreCase("SHAPE")){
return new ShapeFactory();
}else if(choice.equalsIgnoreCase("COLOR")){
return new ColorFactory();
}
return null;
}
}
Step 8
Use the FactoryProducer to get AbstractFactory in order to get factories of concrete classes by passing an information such as type.
AbstractFactoryPatternDemo.java
public class AbstractFactoryPatternDemo {
public static void main(String[] args) {
//get shape factory
AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
//get an object of Shape Circle
Shape shape1 = shapeFactory.getShape("CIRCLE");
//call draw method of Shape Circle
shape1.draw();
//get an object of Shape Rectangle
Shape shape2 = shapeFactory.getShape("RECTANGLE");
//call draw method of Shape Rectangle
shape2.draw();
//get an object of Shape Square
Shape shape3 = shapeFactory.getShape("SQUARE");
//call draw method of Shape Square
shape3.draw();
//get color factory
AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
//get an object of Color Red
Color color1 = colorFactory.getColor("RED");
//call fill method of Red
color1.fill();
//get an object of Color Green
Color color2 = colorFactory.getColor("Green");
//call fill method of Green
color2.fill();
//get an object of Color Blue
Color color3 = colorFactory.getColor("BLUE");
//call fill method of Color Blue
color3.fill();
}
}
Step 9
Verify the output.
Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
Inside Red::fill() method.
Inside Green::fill() method.
Inside Blue::fill() method.
Source :- http://www.tutorialspoint.com/design_pattern/abstract_factory_pattern.htm
Of course you can. Having a Class you can now instantiate it
Object t = c.newInstance()
where c is the Class<?> returned from your method.
Now you can do
Method m = c.getMethod("your_method_name", optional_params_classes_here);
Object result = m.invoke(t, params_here_or_nothing);
Use java reflections. Here is an example of calling 'concat' method of String s :
String s = "Hello, ";
Class myClass = s.getClass();
Method m = myClass.getDeclaredMethod("concat", String.class);
String result = (String)m.invoke(s, "world");
System.out.println(result);

Categories