Identify method's signature using inherited classes in Java's abstract methods - java

I know this is a very simple question, but I have been working in Python for quite a long time and now that I must go back to Java, I seem to have problems changing the chip and wrapping my head around Java's basic polymorphism.
Is it possible to overwrite (implement, to be precise) a class' abstract method in Java using one of the inherited classes as argument?
Let me explain with a very simple example (following the "almost official" example with shapes)
class Shape {}
class Circle extends Shape {}
class Triangle extends Shape {}
abstract class ShapeDrawer {
abstract void draw(Shape s);
}
class CircleDrawer extends ShapeDrawer {
void draw(Circle c){
System.out.println("Drawing circle");
}
}
Is there any way of having Java identifying the draw method in the CircleDrawer class as the implementation of the abstract draw in ShapeDrawer? (The Circle class extends from Shape after all)
Otherwise put: What I'd like is that the draw method of the CircleDrawer class accepts only instances of type Circle, but at the same time, I'd like to tell the Java compiler that the void draw(Circle c) is actually the implementation of the abstract method abstract void draw(Shape s) located in its parent class.
Thank you in advance.

You can solve your problem by means of generics:
public abstract class ShapeDrawer<T extends Shape> {
public abstract void draw(T shape);
}
public class CircleDrawer extends ShapeDrawer<Circle> {
public void draw(Circle circle) { ... }
}

You can't and there is a very good reason why you can't. Take this declaration
public abstract class ShapeDrawer {
public abstract void draw(Shape s);
}
Now take some code that receives a ShapeDrawer and tries to use it:
public void foo(ShapeDrawer drawer, Shape shape) {
drawer.draw(shape);
}
This code should work because the declaration of ShapeDrawer promises that whoever implements it will provide a method called draw() and that method can deal with any Shape.
But if you were allowed to do this:
public class CircleDrawer extends ShapeDrawer {
public void draw(Circle c) {...}
}
That would no longer hold true, your CircleDrawer would be unable to satisfy the promise that it can deal with any Shape.
However imagine this declaration:
public abstract class ShapeCreator {
public abstract Shape create();
}
public class CircleCreator extends ShapeCreator {
public Circle create() {...}
}
Would this work?
Yes, it would(provided that you use Java 5 or later), because unlike the first declaration, what ShapeCreator promises is that it will have a method called create(), which will return a Shape. Since Circle is a Shape, a subclass of ShapeCreator can decide to return only Circles, no promises are broken.
So how do you achieve what you want? See loonytune's answer :)

Not technically, but you can do a hack around it for the functionality you specified.
public abstract ShapeDrawer {
public abstract void draw(Shape s);
}
public CircleDrawer extends ShapeDrawer {
public void draw(Shape s){
if (s instanceof Circle) {
System.out.println("Drawing circle");
}
}
}

No, Java method signatures must match exactly, you can't use subtypes, or you'll overload a method instead of overriding it.
You can return a subtype, but that's it, and return types aren't part of a method signature.

Related

Issue with multiple Interface implementation in Java8 [duplicate]

Two interfaces with same method names and signatures. But implemented by a single class then how the compiler will identify the which method is for which interface?
Ex:
interface A{
int f();
}
interface B{
int f();
}
class Test implements A, B{
public static void main(String... args) throws Exception{
}
#Override
public int f() { // from which interface A or B
return 0;
}
}
If a type implements two interfaces, and each interface define a method that has identical signature, then in effect there is only one method, and they are not distinguishable. If, say, the two methods have conflicting return types, then it will be a compilation error. This is the general rule of inheritance, method overriding, hiding, and declarations, and applies also to possible conflicts not only between 2 inherited interface methods, but also an interface and a super class method, or even just conflicts due to type erasure of generics.
Compatibility example
Here's an example where you have an interface Gift, which has a present() method (as in, presenting gifts), and also an interface Guest, which also has a present() method (as in, the guest is present and not absent).
Presentable johnny is both a Gift and a Guest.
public class InterfaceTest {
interface Gift { void present(); }
interface Guest { void present(); }
interface Presentable extends Gift, Guest { }
public static void main(String[] args) {
Presentable johnny = new Presentable() {
#Override public void present() {
System.out.println("Heeeereee's Johnny!!!");
}
};
johnny.present(); // "Heeeereee's Johnny!!!"
((Gift) johnny).present(); // "Heeeereee's Johnny!!!"
((Guest) johnny).present(); // "Heeeereee's Johnny!!!"
Gift johnnyAsGift = (Gift) johnny;
johnnyAsGift.present(); // "Heeeereee's Johnny!!!"
Guest johnnyAsGuest = (Guest) johnny;
johnnyAsGuest.present(); // "Heeeereee's Johnny!!!"
}
}
The above snippet compiles and runs.
Note that there is only one #Override necessary!!!. This is because Gift.present() and Guest.present() are "#Override-equivalent" (JLS 8.4.2).
Thus, johnny only has one implementation of present(), and it doesn't matter how you treat johnny, whether as a Gift or as a Guest, there is only one method to invoke.
Incompatibility example
Here's an example where the two inherited methods are NOT #Override-equivalent:
public class InterfaceTest {
interface Gift { void present(); }
interface Guest { boolean present(); }
interface Presentable extends Gift, Guest { } // DOES NOT COMPILE!!!
// "types InterfaceTest.Guest and InterfaceTest.Gift are incompatible;
// both define present(), but with unrelated return types"
}
This further reiterates that inheriting members from an interface must obey the general rule of member declarations. Here we have Gift and Guest define present() with incompatible return types: one void the other boolean. For the same reason that you can't an void present() and a boolean present() in one type, this example results in a compilation error.
Summary
You can inherit methods that are #Override-equivalent, subject to the usual requirements of method overriding and hiding. Since they ARE #Override-equivalent, effectively there is only one method to implement, and thus there's nothing to distinguish/select from.
The compiler does not have to identify which method is for which interface, because once they are determined to be #Override-equivalent, they're the same method.
Resolving potential incompatibilities may be a tricky task, but that's another issue altogether.
References
JLS 8.4.2 Method Signature
JLS 8.4.8 Inheritance, Overriding, and Hiding
JLS 8.4.8.3 Requirements in Overriding and Hiding
JLS 8.4.8.4 Inheriting Methods with Override-Equivalent Signatures
"It is possible for a class to inherit multiple methods with override-equivalent signatures."
This was marked as a duplicate to this question https://stackoverflow.com/questions/24401064/understanding-and-solving-the-diamond-problems-in-java
You need Java 8 to get a multiple inheritance problem, but it is still not a diamon problem as such.
interface A {
default void hi() { System.out.println("A"); }
}
interface B {
default void hi() { System.out.println("B"); }
}
class AB implements A, B { // won't compile
}
new AB().hi(); // won't compile.
As JB Nizet comments you can fix this my overriding.
class AB implements A, B {
public void hi() { A.super.hi(); }
}
However, you don't have a problem with
interface D extends A { }
interface E extends A { }
interface F extends A {
default void hi() { System.out.println("F"); }
}
class DE implement D, E { }
new DE().hi(); // prints A
class DEF implement D, E, F { }
new DEF().hi(); // prints F as it is closer in the heirarchy than A.
As far as the compiler is concerned, those two methods are identical. There will be one implementation of both.
This isn't a problem if the two methods are effectively identical, in that they should have the same implementation. If they are contractually different (as per the documentation for each interface), you'll be in trouble.
There is nothing to identify. Interfaces only proscribe a method name and signature. If both interfaces have a method of exactly the same name and signature, the implementing class can implement both interface methods with a single concrete method.
However, if the semantic contracts of the two interface method are contradicting, you've pretty much lost; you cannot implement both interfaces in a single class then.
Well if they are both the same it doesn't matter. It implements both of them with a single concrete method per interface method.
As in interface,we are just declaring methods,concrete class which implements these both interfaces understands is that there is only one method(as you described both have same name in return type). so there should not be an issue with it.You will be able to define that method in concrete class.
But when two interface have a method with the same name but different return type and you implement two methods in concrete class:
Please look at below code:
public interface InterfaceA {
public void print();
}
public interface InterfaceB {
public int print();
}
public class ClassAB implements InterfaceA, InterfaceB {
public void print()
{
System.out.println("Inside InterfaceA");
}
public int print()
{
System.out.println("Inside InterfaceB");
return 5;
}
}
when compiler gets method "public void print()" it first looks in InterfaceA and it gets it.But still it gives compile time error that return type is not compatible with method of InterfaceB.
So it goes haywire for compiler.
In this way, you will not be able to implement two interface having a method of same name but different return type.
Try implementing the interface as anonymous.
public class MyClass extends MySuperClass implements MyInterface{
MyInterface myInterface = new MyInterface(){
/* Overrided method from interface */
#override
public void method1(){
}
};
/* Overrided method from superclass*/
#override
public void method1(){
}
}
The following two approaches can also be taken to implement both the duplicate methods and avoid ambiguity -
APPROACH 1:
App.java -
public class App {
public static void main(String[] args) {
TestInterface1 testInterface1 = new TestInterface1();
TestInterface2 testInterface2 = new TestInterface2();
testInterface1.draw();
testInterface2.draw();
}
}
TestInterface1.java -
public class TestInterface1 implements Circle {
}
TestInterface2.java -
public class TestInterface2 implements Rectangle {
}
Circle.java -
public interface Circle extends Drawable {
#Override
default void draw() {
System.out.println("Drawing circle");
}
}
Rectangle.java -
public interface Rectangle extends Drawable {
#Override
default void draw() {
System.out.println("Drawing rectangle");
}
}
Drawable.java -
public interface Drawable {
default void draw() {
System.out.println("Drawing");
}
}
Output -
Drawing circle
Drawing rectangle
APPROACH 2:
App.java -
public class App {
public static void main(String[] args) {
Circle circle = new Circle() {
};
Rectangle rectangle = new Rectangle() {
};
circle.draw();
rectangle.draw();
}
}
Circle.java -
public interface Circle extends Drawable {
#Override
default void draw() {
System.out.println("Drawing circle");
}
}
Rectangle.java -
public interface Rectangle extends Drawable {
#Override
default void draw() {
System.out.println("Drawing rectangle");
}
}
Drawable.java -
public interface Drawable {
default void draw() {
System.out.println("Drawing");
}
}
Output -
Drawing circle
Drawing rectangle

Interface implementation by both parent and sub class in java

If the base class and sub class implements the same interface and the method implementation of the abstract method is provided in the base class then do we have to provide the implementation in sub class also?
Yes you can, and the implementation from subclass executes when you have initialisation paradigm
BaseClass v = new SubClass();
That's quite normal polymorphism/ovveriding.
Related : Can an interface extend multiple interfaces in Java?
do we have to provide the implementation in sub class also
No, you don't have to do it. If one class extends another, it already has all (public and protected) methods declared in parent class.
But you can provide a different implementation of this method. In this case the method from the parent class will be overriden.
There is no need of implementing the same interface in both parent and child classes as because if you are implementing it in parent class then child will also have the same method but if you want to override you can override it.
public interface Shape {
void draw();
}
class Parallelogram implements Shape {
public void draw() {
System.out.println("This is Parallelogram");
}
}
public class Square extends Parallelogram {
#Override
public void draw() {
System.out.println("This Parallelogram is Square");
}
public static void main(String args[0]) {
Square square = new Square();
square.draw();
}
}
//Output
This Parallelogram is Square
public class Rhombus extends Parallelogram {
public static void main(String args[0]) {
Rhombus rhombus = new Rhombus();
rhombus.draw();
}
}
//Output
This is Parallelogram
It should not be required as subclass already has the method implementation in base class

Abstract Factory Pattern - unused code

I'm learning Desgin patterns and come across very weird example in HERE. If we got a class:
public abstract class AbstractFactory {
abstract Color getColor(String color);
abstract Shape getShape(String shape) ;
}
which as we can see, has 2 types of methods which creates Objects: colors and shapes. This class is abstract so we have to create concrete implementation of this, so lets assume that we have:
public class ShapeFactory extends AbstractFactory {
#Override
public Shape getShape(String shapeType){
// I skip implementation to keep post brief
}
#Override
Color getColor(String color) {
return null; // It's useless method in this class!
}
}
and second implementation:
public class ColorFactory extends AbstractFactory {
#Override
public Shape getShape(String shapeType){
return null; // It's useless method in this class!
}
#Override
Color getColor(String color) {
// I skip implementation to keep post brief
}
}
And here comes my question, in both cases (concrete factories) there is an method that is completly useless and shoudn't be there, but as we created AbstractFactory class we have to implement both methods. Isn't it bad practice in programming to create useless methods in classes that don't need it? Should it be done in other way not as website suggest?
#Michael213 - Your concrete implementations are not correct. For sure they do not follow Abstract Factory pattern. Abstract factory talks about families of product. abstract factory sample (with my assumptions) will look like following code. your example using only one method will be misuse of pattern and will break soon.
I have already answer similar question please have a look to that also What are the real benefits of using the Abstract Factory in the following example, instead of the factory method?
public abstract class AbstractFactory {
abstract Color getColor(String color);
abstract Shape getShape(String shape) ;
}
/**
* CONCRETE FACTORY1
*/
class HighResolutionFactory extends AbstractFactory{
Color getColor(String color){
return new HighResolutionColor();
}
Shape getShape(String shape){
return new HighResolutionShape();
}
}
/**
* CONCRETE FACTORY2
*/
class LowResolutionFactory extends AbstractFactory{
Color getColor(String color){
return new LowResolutionColor();
}
Shape getShape(String shape){
return new LowResolutionShape();
}
}
class Color{} // ABSTRACT PRODUCT 1
class Shape{} // ABSTRACT PRODUCT 2
class HighResolutionColor extends Color{}// CONCRETE PRODUCT1 FACT 1
class HighResolutionShape extends Shape{}// CONCRETE PRODUCT2 FACT 1
class LowResolutionColor extends Color{}//...
class LowResolutionShape extends Shape{}
Yes, that tutorial doesn't seem the best in that regards.
It is not ideal although it still counts as a factory design pattern.
AbstractFactory is wrong. You do not have to think of a factory that makes different objects. It is right to make separate factories for each different type.
public interface AbstractColorFactory {
public Color getColor(String color);
}
public interface AbstractShapeFactory {
public Shape getShape(String shape);
}
public class ColorFactory implements AbstractColorFactory {
public Color getColor(String color) {
return ....
}
}
public class ShapeFactory implements AbstractShapeFactory {
public Shape getShape(String shape) {
return ....
}
}

Java Factory Pattern With Generics

I would like my BallUserInterfaceFactory to return an instance of a user interface that has the proper generic type. I am stuck in the example below getting the error:
Bound mismatch: The generic method getBaseballUserInterface(BASEBALL)
of type BallUserInterfaceFactory is not applicable for the arguments
(BALL). The inferred type BALL is not a valid substitute for the
bounded parameter
public class BallUserInterfaceFactory {
public static <BALL extends Ball> BallUserInterface<BALL> getUserInterface(BALL ball) {
if(ball instanceof Baseball){
return getBaseballUserInterface(ball);
}
//Other ball types go here
//Unable to create a UI for ball
return null;
}
private static <BASEBALL extends Baseball> BaseballUserInterface<BASEBALL> getBaseballUserInterface(BASEBALL ball){
return new BaseballUserInterface<BASEBALL>(ball);
}
}
I understand that it cannot guarantee that BALL is a Baseball, and so there is a parameter type mismatch on the getBaseballUserInterface method call.
If I cast the ball parameter in the getBaseballUserInterface method call, then I get the error:
Type mismatch: cannot convert from BaseballUserInterface<Baseball>
to BallUserInterface<BALL>
Because it can't guarantee that what I am returning is the same type of BALL.
My question is, what is the strategy for dealing with this situation?
(For completeness, here are the other classes required in the example)
public class Ball {
}
public class Baseball extends Ball {
}
public class BallUserInterface <BALL extends Ball> {
private BALL ball;
public BallUserInterface(BALL ball){
this.ball = ball;
}
}
public class BaseballUserInterface<BASEBALL extends Baseball> extends BallUserInterface<BASEBALL>{
public BaseballUserInterface(BASEBALL ball) {
super(ball);
}
}
This is a wrong design pattern. Rather than using one generic method and an if ladder, you should instead use overloading. Overloading eliminates the need for the if ladder and the compiler can make sure the correct method is invoked rather than having to wait till runtime.
eg.
public class BallUserInterfaceFactory {
public static BallUserInterface<Baseball> getUserInterface(
Baseball ball) {
return new BallUserInterface<Baseball>(ball);
}
public static BallUserInterface<Football> getUserInterface(
Football ball) {
return new BallUserInterface<Football>(ball);
}
}
This way you also get the added benefit of compile time errors if your code cannot create a BallUserInterface for the appropriate ball.
To avoid the if ladder you can use a technique known as double dispatch. In essence, we use the fact that the instance knows what class it belongs to and calls the appropriate factory method for us. For this to work Ball needs to have a method that returns the appropriate BallInterface.
You can either make the method abstract or provide a default implementation that throws an exception or returns null. Ball and Baseball should now look something like:
public abstract class Ball<T extends Ball<T>> {
abstract BallUserInterface<T> getBallUserInterface();
}
.
public class Baseball extends Ball<Baseball> {
#Override
BallUserInterface<Baseball> getBallUserInterface() {
return BallUserInterfaceFactory.getUserInterface(this);
}
}
To make things a little neater, it's better to make getBallUserInterface package private and provide a generic getter in BallUserInterfaceFactory. The factory can then manage additional checks like for null and any thrown exceptions. eg.
public class BallUserInterfaceFactory {
public static BallUserInterface<Baseball> getUserInterface(
Baseball ball) {
return new BallUserInterface<Baseball>(ball);
}
public static <T extends Ball<T>> BallUserInterface<T> getUserInterface(
T ball) {
return ball.getBallUserInterface();
}
}
The Visitor Pattern
As pointed out in the comments, one problem of the above is it requires the Ball classes to have knowledge of the UI, which is highly undesirable. You can, however, use the visitor pattern, which enables you to use double dispatch, but also decouples the various Ball classes and the UI.
First, the necessary visitor classes, and factory functions:
public interface Visitor<T> {
public T visit(Baseball ball);
public T visit(Football ball);
}
public class BallUserInterfaceVisitor implements Visitor<BallUserInterface<? extends Ball>> {
#Override
public BallUserInterface<Baseball> visit(Baseball ball) {
// Since we now know the ball type, we can call the appropriate factory function
return BallUserInterfaceFactory.getUserInterface(ball);
}
#Override
public BallUserInterface<Football> visit(Football ball) {
return BallUserInterfaceFactory.getUserInterface(ball);
}
}
public class BallUserInterfaceFactory {
public static BallUserInterface<? extends Ball> getUserInterface(Ball ball) {
return ball.accept(new BallUserInterfaceVisitor());
}
// other factory functions for when concrete ball type is known
}
You'll note that the visitor and the factory function have to use wildcards. This is necessary for type safety. Since you don't know what type of ball has been passed, the method cannot be sure of what UI is being returned (other than it is a ball UI).
Secondly, you need to define an abstract accept method on Ball that accepts a Visitor. Each concrete implementation of Ball must also implement this method for the visitor pattern to work correctly. The implementation looks exactly the same, but the type system ensures dispatch of the appropriate methods.
public interface Ball {
public <T> T accept(Visitor<T> visitor);
}
public class Baseball implements Ball {
#Override
public <T> T accept(Visitor<T> visitor) {
return visitor.visit(this);
}
}
Finally, a bit of code that can put all this together:
Ball baseball = new Baseball();
Ball football = new Football();
List<BallUserInterface<? extends Ball>> uiList = new ArrayList<>();
uiList.add(BallUserInterfaceFactory.getUserInterface(baseball));
uiList.add(BallUserInterfaceFactory.getUserInterface(football));
for (BallUserInterface<? extends Ball> ui : uiList) {
System.out.println(ui);
}
// Outputs:
// ui.BaseballUserInterface#37e247e2
// ui.FootballUserInterface#1f2f0ce9
This is a VERY GOOD question.
You could cast brutely
return (BallUserInterface<BALL>)getBaseballUserInterface((Baseball)ball);
The answer is theoretically flawed, since we force BASEBALL=Baseball.
It works due to erasure. Actually it depends on erasure.
I hope there is a better answer that is reification safe.
public class BaseballUserInterface extends BallUserInterface<Baseball> {
public BaseballUserInterface(Baseball ball) {
super(ball);
}
}
You are using the BallUserInterface as a result of the factory method. So, it can be hidden which concrete ball is used:
public class BallUserInterfaceFactory {
public static BallUserInterface<?> getUserInterface(Ball ball) {
if(ball instanceof Baseball){
return getBaseballUserInterface((Baseball)ball);
}
return null;
}
private static BaseballUserInterface getBaseballUserInterface(Baseball ball){
return new BaseballUserInterface(ball);
}
}
If the client is interested in the type of the ball you should offer a factory method with the concrete ball as parameter:
public static BaseballUserInterface getUserInterface(Baseball ball){
return new BaseballUserInterface(ball);
}

concrete class method keeps throwing an exception from abstract class despite implementation

I have an abstract class Automobile which has an unimplemented method called move
so
public abstract class Automobile {
public void move() {
throw new UnsupportedOperationException();
}
}
I have a concrete class which extends my abstract class and implements the move method.My problem is the method keeps throwing an UnsupportedOperationException
public class Car extends Automobile{
int x;
public void move(){
x++;
}
}
It could be for many reasons in your concrete class: maybe your concrete doesn't actually extends Foo? Or maybe it calls super.move() somewhere in its body.
Instead of throwing an exception, the correct way is to define the class and method as abstract to force subclasses to override it.
public abstract class Foo {
public abstract void move();
}
Please note if Foo only has abstract methods, like in the example above, that's an interface that you want, not an abstract class. Also, you should name it to define a behaviour
public interface Moving {
void move();
}
And then:
public class MovingObject implements Moving {
....
#Override
public void move() {
// your implementation
}
....
}
Are you calling super.move() in your implementation class? Eclipse generates that call by default if you used Source->Override/Implement Methods...
Otherwise I think, that you did not override the method correctly.

Categories