I don't know if this is at all possible, but I was thinking of something in Java:
If I have an abstract parent class, I can do this:
public ParentClass add(ParentClass a, ParentClass b);
If ParentClass then has a child and I want to override this method, the child class will still have a ParentClass add(ParentClass, ParentClass) method.
Is there a way to make the parent function derive itself to each child?
I don't know if I'm wording it right, but something like this:
// ParentClass.java
public ParentClass add(ParentClass a, ParentClass b);
// Foo.java
#Override // or an equivalent
public Foo add(Foo a, Foo b) {}
// Bar.java
#Override
public Bar add(Bar a, Bar b) {}
Notice how each child doesn't have a ParentClass add(...) function, but rather one for each of their own types instead?
Obviously I can just make these myself, but I want to be able to create overridable ones in parents. I've never seen this in practice before, so I doubt its existence. I just want to clarify with someone with a higher Java knowledge than me. Thanks.
In theory, which I guess no language has ever done, something like this:
public child add(child a, child b);
// where *child* is the type of the child inheriting the method
In Java covariance of parameters of a method is not allowed.
This inherited method : public ParentClass add(ParentClass a, ParentClass b);
is legal for all children as it will allow to specify any subclass of ParentClass as parameters.
It is more flexible.
Now, if you don't want this flexibility and you want to force a specific type for parameters in the inherited method, you should use a generics abstract class.
public abstract class ParentClass <T extends ParentClass <?>>{
public abstract ParentClass<?> add(T a, T b);
}
And in child class you could write :
public class ChildClass extends ParentClass <ChildClass>{
public ParentClass<?> add(ChildClass a, ChildClass b){
....
}
}
Something like this could work with Generics:
public abstract class ParentClass<T extends ParentClass> {
public abstract T add(T a, T b);
}
class Foo extends ParentClass<Foo> {
#Override
public Foo add(Foo a, Foo b) {
return null;
}
}
class Bar extends ParentClass<Bar> {
#Override
public Bar add(Bar a, Bar b) {
return null;
}
}
Related
I would like to create an Java interface with a method that accepts all subtypes of a type:
interface A{};
interface B{
void method(A a);
}
What I want to accomplish is to make an implementation of the method(A a) accept
all subtypes of A (like return type polymorphism but with an argument).
Is this even possible?
You've already done it!
To prove it, try something like this:
public class ThisA implements A {}
public class ThatA implements A {}
public class OtherA implements A {}
public class SubclassA extends OtherA {}
then call your method:
B b = new B {
public void method(A a) {
System.out.println("Called with "+a);
}
}
b.method(new ThisA());
b.method(new ThatA());
b.method(new OtherA());
b.method(new SubclassA());
I have this abstract class:
public abstract class Foo{
//some attributes
public Foo(params){}
public abstract SomeInterface search(Long id);
public abstract boolean insert(SomeInterface param);
}
I have the following class:
public class InterfaceImplementation implements SomeInterface {
//Some code here
}
Then I create an instance of Foo:
public class Bar extends Foo{
public Foo(params){
super(params);
}
#Override
public InterfaceImplementation search(Long id){
// some code here
}
// The above code compiles
#Override
public boolean insert(InterfaceImplementation param){
// some code specific to the InterfaceImplementation here
}
// This function does not compile/
}
So, what am I doing wrong and how can I achieve what I'm trying to do?
Your class Bar doesn't override insert, because the parameter types must match exactly. This is because your implementation takes an InterfaceImplementation, not a SomeInterface.
What you can do to get this to compile:
Take a SomeInterface as a parameter in Bar's insert method, because any subclass should be able to process any implementation of SomeInterface, as specified by Foo.
OR
Introduce generics in SomeInterface to specify what should be the parameter type.
public abstract class Foo<T extends SomeInterface>{
and
public abstract boolean insert(T param);
Then you can specify what T is in the subclass:
public class Bar extends Foo<InterfaceImplementation>{
and
#Override
public boolean insert(InterfaceImplementation param){
Let's say I had
Foo foo = new Bar();
and tried to do
foo.insert(new OtherInterfaceImpl());
I would be allowed to do this because Foo#insert accepts a SomeInterface and OtherInterfaceImpl implements SomeInterface.
However, Bar's implementation of insert could not accept a OtherInterfaceImpl since you specifically said so with this declaration
public boolean insert(InterfaceImplementation param){
This would break type safety and is therefore not allowed.
You can use generics as rgettman has shown.
You cannot restrict parameters when implememting an superclass method.
You can restrict the output to subtypes.
Consider the method
Number sum(Number a, Number b);
which may be used with arbitrary numbers, e.g.
Number out = sum(Double.valueOf(1.23), Integer.valueOf(7));
and the "candidates"
Double sum(Number a, Number b) {
return a.doubleValue() + b.doubleValue()
}
vs.
Number sum(Integer a, Double b) {
return (Byte) (a.doubleValue() + b.doubleValue());
}
Which of the two implements above API correctly?
I have two interfaces. An interface A, and interface B, which extends interface A. Now, I have class which likes to keep reference of object that either implements A or B. And I would like to provide setter for it. I tried below, but getting type mis match exception.
public interface A {
}
public interface B extends A {
}
public class AB {
private Class<? extends A> object;
public void setObject(Class<? extends A> o){
this.object = o;
}
}
So basically, I would like setObject method to accept an object that either implements interface A or B.
Simple answer:
Type it as A: setObject(A a).
A class that implements B also implements A. Full code:
public class UsesA {
private A a;
public void setObject(A a){
this.a = a;
}
}
Now, if you really want to work with B, you'd type it as B, which would also allow you to treat it as an A, since B inherits from it:
public class UsesB {
private B b; // can call A's methods on this field
public void setObject(B b) {
this.b = b;
}
}
But now you can't pass an A (static) reference to setObject. If you really want to do this, then you'd need to first downcast it as a B, which could fail at runtime. Generics will not improve on this.
If you have an object implementing B, it will also be an instance of A. Because of this, you can make setObject accept any A, which will allow instances of A or B to be passed to it.
public void setObject(A a){
this.object = a;
}
Your code doesn't actually match up with your question. You've stated that
I have class which likes to keep reference of object that either
implements A or B
but the field (called object) is actually a Class, not an Object (instance of a Class).
Your code works if you were truly trying to have your setter accept any interface that extends A. But as you probably realize now from the other answers, you actually want an instance of A :)
public class AB {
private Class<? extends A> type; // renamed from object for clarity
public void setObject(Class<? extends A> type) {
this.type = type;
}
#Test
public void testSetter() {
setObject(A.class); // no errors
setObject(B.class); // no errors
}
}
As suggested earlier if you will use (A a) it will work since B is a type of A. Hence child class can always be represents it's parent.
Say I have a class Foo, a class A and some subclass B of A. Foo accepts A and its sublclasses as the generic type. A and B both require a Foo instance in their constructor. I want A's Foo to be of type A , and B's Foo to be of type B or a superclass of B. So in effect, So I only want this:
Foo<X> bar = new Foo<X>;
new B(bar);
to be possible if X is either A, B, or a both subclass of A and superclass of B.
So far this is what I have:
class Foo<? extends A>{
//construct
}
class A(Foo<A> bar){
//construct
}
class B(Foo<? super B> bar){
super(bar);
//construct
}
The call to super(...) doesn't work, because <A> is stricter than <? super B>. Is it somehow possible to use the constructor (or avoid code duplication by another means) while enforcing these types?
Edit: Foo keeps a collection of elements of the generic parameter type, and these elements and Foo have a bidirectional link. It should therefore not be possible to link an A to a Foo.
If you change the A constructor to:
class A(Foo<? extends A> bar){
//construct
}
will it do what you want ?
If you really want to limit the constructor of A to Foo then you need to provide another protected method (aka usable from derived classes) to set the Foo instance.
Something like this:
public class A {
Foo<?> foo;
public A(Foo<A> foo) {
setFoo(foo);
}
protected A() {
}
protected void setFoo(Foo<?> foo) {
this.foo = foo;
}
}
and B
public class B extends A {
public B(Foo<? super B> foo) {
setFoo(foo);
}
}
now this works:
new A(new Foo<A>());
new A(new Foo<B>()); // this fails compilation
new B(new Foo<B>());
In order for foo element in A to be properly typed you might need to make A a parametrized class too.
The only way to do this would be to have...
class A(Foo<? extends A> bar) {
//construct
}
But it appears this isn't what you want. You can't have the other approach because when you create an instance of B you are also creating an instance of A (that is part of the B instance). So B can't take in special fields for the parts in A. I'm not sure why you wouldn't allow A's foo to be of type B, could you perhaps expand on that?
The following setup compiled for me:
public interface MarkerInterface {
}
public class A implements MarkerInterface {
public A(Foo<A> fooA) {
}
}
public class SuperB implements MarkerInterface {
}
public class B extends SuperB {
public B(Foo<? super B> fooB) {
}
}
And with the main method:
public static void main(String[] args) {
B b = new B(new Foo<SuperB>());
}
Is this what you're looking for?
Java generics are powerful and well designed; nevertheless we sometimes find them lacking. I don't think there's a good way to do what you want.
The easiest thing to do is to change the declaration of Foo<X> to Foo<X extends A>. If that's not acceptable, you can subclass Foo like this:
class Foo<X> { }
class FooA<X extends A> extends Foo<X> { }
class A {
public A(FooA<? extends A> foo) { }
}
class B extends A {
public B(FooA<? super B> foo) {
super(foo);
}
}
(Note: if you have trouble following, when you see Foo, think ArrayList.)
This has the obvious disadvantage that you have to use FooA rather than Foo, hindering code reuse.
Basically I want to do this:
public interface A {
void a();
}
public interface B {
void b();
}
public class SomeClass {
public SomeClass(<A&B> e) { // Note the type here
e.a();
e.b();
}
}
What I did on the commented line is obviously illegal. I know I can just require the passed object to implement interface A, or interface B, but is there a way to do both?
I guess there are workarounds (like requiring the parameter to be of type A and then check if it is also an instanceof B), but that way I don't get help from the compiler. Do you know of any way to do this? Or maybe a smarter workaround...
You can do it with generics enabled. For example, to accept an instance of some class that implements both CharSequence and Appendable:
public <T extends CharSequence & Appendable> void someMethod(T param) {
...
}
Depending on the design, you can do one of the following:
Make A : B or B : A.
Make an interface C : A, B.
Either way you'll want to have contract that includes both a() and b().
Well, there is the <T extends A & B> f(T ab) notation, but you should favour composition over inheritance. You don't really have to extend anything. Just make a type that is the joint union (product) of both types A and B, as follows:
public abstract class P2<A, B> {
public A _1();
public B _2();
}
Sometimes called a product-2, or a "pair" type. You can create a handy constructor for these:
public final class P {
private P() {}
public static <A, B> P2 p(final A a, final B b) {
return new P2<A, B>() {
public A _1() {
return a;
}
public B _2() {
return b;
}
}
}
}
Note that you can use the same object for both arguments, if A and B are interfaces and your object implements both of them:
P2<A, B> both = P.p(o, o);
Or you're free to use two different objects, making the design nice and decoupled.
You'll find this type, as well as products of up to 8 types, included in the Functional Java library. There's also a type called Either<A, B> that is the disjoint union (sum) of two types, such that it holds a value that is of either type A or B (or both).
Just shooting in the dark, I don't know if this is the correct syntax, ie if you have to redeclare the methods in C but what about this:
public interface A {
void a();
}
public interface B {
void b();
}
public interface C extends A, B{}
public class SomeClass{
public SomeClass(C e) { // Note the type here
e.a();
e.b();
}
}
If you have a method that needs two different interfaces as parameters, just make it take two parameters.
public void foo(A a, B b) {
....
}
It’s not that hard, believe me.