I have two Java classes B and C in which both extend from class A (I do not own class A).
public class B extends A {…}
public class C extends A {…}
I need a list of type „ListItem“ to hold instances of either B or C, but since both (B and C) are already extended, they cannot be further extended by using „ListItem“ as a superclass.
I think the only way to go is with composition („has-a“ relation…).
Since „ListItem“ should never have B AND C (but only one of them), I am planning to create ListItem with 2 constructors and set an appropriated
inner type to reflect if either B or C is being hold.
Is there a better approach to accomplish this? Please see the pseudo code below.
public class ListItem {
private enum elemType {
TYPE_B, TYPE_C
}
private final B mBItem;
private final C mCItem;
private final elemType mType;
// used to hold instance of B
public ListItem(B b) {
this.mBItem = b;
this.mType = TYPE_B;
}
// used to hold instance of C
public ListItem(C c) {
this.mCItem = c;
this.mType = TYPE_C;
}
// sample method to demonstrate delegation
private int getAge() {
int age;
if (containsB()) {
age = mBItem.getAge();
}
else if (containsC()) {
age = mCItem.getAge();
}
else {…}
return age;
}
private boolean containsB() {
return (mType == TYPE_B);
}
private boolean containsC() {
return (mType == TYPE_C);
}
}
I mean, you have:
public class B extends A {…}
public class C extends A {…}
So you could just make your item hold an A:
public class ListItem {
private final A item;
public ListItem (A item) {
this.item = item;
}
}
And you have any number of options on how to handle it from there, e.g. simply:
public A getItem () {
return item;
}
And do any appropriate casts or tests from the caller. That's the most flexible way. Or I suppose something like:
public B getB () {
return item instanceof B ? (B)item : null;
}
public C getC () {
return item instanceof C ? (C)item : null;
}
But that's starting to get sloppy, and limits you from storing any other A-derived stuff in your ListItem.
You might want to start questioning your design here. For example, if you're adding some functionality to A that is common to B and C and necessary for the proper operation of a ListItem, consider deriving some class from A to add the common stuff, derive B and C from that, and make your ListItem store that base (of course, if you do this you can't store an A any more):
public class AgedA extends A {
...
public int getAge () { return ... }
}
// Then your B and C both extend AgedA, and your ListItem stores an
// AgedA and can use getAge().
You could make AgedA be abstract and getAge() be virtual, if that's more appropriate. Or you could declare an interface that defines getAge() and use that.
Yet another option is you could (as pointed out in comments) make ListItem be either an interface, or a class that extends A, then have your B and C implement or extend that.
I suppose you could also use generics for ListItem e.g. <? extends A>, although that may not be appropriate especially if your ListItems are mixed. The major benefit of using generics is that e.g. getters can now directly return the subtypes without casts and you give yourself compile-time ability to restrict types to a specific subtype in function parameters and stuff, but otherwise it's essentially the same as just storing an A.
In any case, aside from the advice to just store A in ListItem and handle different types at a higher level, I can't in good conscience give you any other approach suggestions, because the need for all of this seems questionable to me.
I think a clean approach to this is to have your ListItem be an abstract class extending from A, then have B and C extend from ListItem.
Why make ListItem abstract? Any behavior that is shared across B and C can be implemented in the abstract class, and you can additionally impose interfaces requirements on its subclasses.
public abstract class ListItem extends A {
public int getAge () {
// Both B and C share this implementation
}
// But B and C behave differently for this method
public abstract void manipulate ();
}
public class B extends ListItem {
public void manipulate () {
// Something specific to B here.
}
}
public class C extends ListItem {
public void manipulate () {
// Something specific to C here.
}
}
Then you can declare your list of ListItems, insert instances of B and C as necessary, and manipulate them according to the concrete methods or the abstract interface in ListItem:
ArrayList<ListItem> list = new ArrayList<>();
list.add(new B());
list.add(new C());
System.out.println(list.get(0).getAge());
list.get(1).manipulate();
From your description it looks like ListItem is a container for items of type A (B or C, other sub classes in the future). I would recommend using generics, using <? extends A>, you wouldn't then need the more than one constructor and all of A's methods should be available.
Related
I came to a problem with interfaces in a program I'm making. I want to create a interface which have one of its methods receiving/returning a reference to the type of the own object. It was something like:
public interface I {
? getSelf();
}
public class A implements I {
A getSelf() {
return this;
}
}
public class B implements I {
B getSelf() {
return this;
}
}
I can't use an "I" where it's a "?", because I don't want to return a reference to the interface, but the class. I searched and found that there are no way to "self-refer" in Java, so I can't just substitute that "?" in the example for a "self" keyword or something like this. Actually, I came up to a solution that goes like
public interface I<SELF> {
SELF getSelf();
}
public class A implements I<A> {
A getSelf() {
return this;
}
}
public class B implements I<B> {
B getSelf() {
return this;
}
}
But it really seems like a workaround or something alike. Is there another way to do so?
There is a way to enforce using ones own class as a parameter when extending an interface:
interface I<SELF extends I<SELF>> {
SELF getSelf();
}
class A implements I<A> {
A getSelf() {
return this;
}
}
class B implements I<A> { // illegal: Bound mismatch
A getSelf() {
return this;
}
}
This even works when writing generic classes. Only drawback: one has to cast this to SELF.
As Andrey Makarov noted in a comment below this does not work reliably when writing generic classes.
class A<SELF extends A<SELF>> {
SELF getSelf() {
return (SELF)this;
}
}
class C extends A<B> {} // Does not fail.
// C myC = new C();
// B myB = myC.getSelf(); // <-- ClassCastException
Java supports covariant return types, so that's one option. Take advantage of the fact that both A and B are derived from Object:
public interface I {
Object getSelf(); // or I, see below
}
public class A implements I {
A getSelf() { return this; }
}
public class B implements I {
B getSelf() { return this; }
}
The point is that both A.getSelf() and B.getSelf() are legitimate overrides of I.getSelf(), even though their return type is different. That's because every A can be treated like an Object, and so the return type is compatible with that of the base function. (This is called "covariance".)
In fact, since A and B are also known to derive from I, you can replace Object by I for the same reasons.
Covariance is generally a Good Thing: Someone who has an interface object of type I can call getSelf() and get another interface, and that's all she needs to know. On the other hand, someone who already knows he has an A object can call getSelf() and will actually get another A object back. The additional information can be used to get a more specific derived type, but someone who lacks that information still gets everything that's prescribed by the interface base class:
I x = new A();
A y = new A();
I a = x.foo(); // generic
A b = y.foo(); // we have more information, but b also "is-an" I
A c = (A)x.foo(); // "cheating" (we know the actual type)
I was wondering if there are any other way to do so?
You can write it as follows:
public interface I {
I getSelf();
}
and then cast the result to the type you want. Your existing A and B classes will work as-is.
(This is an example of return type covariance. Support for return type covariance was added in Java 5. This approach will give compilation errors in older JDKs.)
The alternative version (you call it a work-around, but it isn't really) that uses generics allows you to avoid the explicit typecast. However, there is an implicit typecast in the generated code, and at runtime ... unless the JIT compiler can optimize it away.
There are no better alternatives, AFAIK.
As others have said, you can override the return type in the implementing classes:
public interface I {
public I getSelf();
}
public class A implements I {
#Override
public A getSelf() {
return this;
}
}
However, I have two 'why' questions for you:
1: Why do you want an Interface to return the implementing object? It seems to run against the general ideas of interfaces and inheritance to me. Can you show an example of how this might be used?
2: In any case, why would you want this function? If a.getSelf() == a, why not just use a?
In some code I am working with I have an existing third party API that implements things extending from A (and perhaps not directly, but via X, and perhaps also implementing a bunch of other interfaces).
Now for the code I am working on, I have an interface IB, that provides additional capabilities to what A offers. As such a lot of my code actually has the requirement that the object passed to it extends A, and also implements IB, but there is no way to declare that for my member variables I can think of. But picking either A or IB results in a lot of casts.
I guess if A was/had an interface IA would solve this, but there is no way I can change A, or for my implementations of IB to not need to extend A (the third party code uses A, and takes care of a lot of management, persistence, networking, user interfacing, etc. via it).
class Z {
private List<?what here?> items;
/**The implementer of IB should know how to find the Z instance and call this.*/
private void subscribe(? item) {
items.add(item);
}
public void doSomethingWithItems() {
...code thats requires facilities from A and IB...
}
You can specify a type intersection:
<T extends A & IB>
The rules are that if one of the types is a class, it must be listed first.
I would type the class if you can:
class Z<T extends A & IB> {
private List<T> items;
private void subscribe(T item) {
items.add(item);
}
public void doSomethingWithItems() {
// the items are both A and IB
}
}
If you can't type Z, go for typed methods:
class Z {
private List<A>items;
private <T extends A & IB> void subscribe(T item) {
items.add(item);
}
public void doSomethingWithItems() {
// items are A, but if you want IB functionality you must cast.
// the cast is safe if items are only added via subscribe()
}
}
Use a generic helper class, whose type parameter lets you use a type intersection:
class Z {
private static final class Wrapper<T extends A & IB> {
private final T item;
Wrapper(final T item) {
this.item = item;
}
void doWork() {
// code thats requires facilities from A and IB
}
}
private List<Wrapper<?>> wrappers;
private <T extends A & IB> void subscribe(T item) {
wrappers.add(new Wrapper<T>(item));
}
public void doSomethingWithItems() {
for (final Wrapper<?> wrapper : wrappers) {
wrapper.doWork();
}
}
I gave a similar answer on this post: Java generics type mismatch in method signature
It would be most ideomatic if IB were a subtype of IA, but if you can't do that ...
It is difficult to express this in code, as Java does not support first class intersection types. That is, Java only supports intersection types in bounds of type parameters, and we can't use a type parameter in the field declaration without requiring that all elements of the list are of the same subtype of IB.
Therefore, the best approximation I can think of is to enforce the constraint only in the public API, and use casts internally:
class Z {
private List<A> items;
private <B extends A & IB> void subscribe(B item) {
items.add(item);
}
public void doSomethingWithItems() {
for (A a : items) {
IB b = (IB) a; // safe because we checked it on subscription
// use features of A and IB
}
}
}
Yes, it is ugly. That's why newer JVM languages such a Ceylon feature first class intersection types. That is, in Ceylon, one could simply write:
class Z() {
List<A & IB> items;
void subscribe(A & IB item) {
items.add(item);
}
void doSomethingWithItems() {
for (item in items) {
// use features of A and IB
}
}
}
You could make a new abstract class, that both implements IB with abstract methods, and extends A. Then you could make all the classes that you need to use extend your new abstract class.
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.
I came to a problem with interfaces in a program I'm making. I want to create a interface which have one of its methods receiving/returning a reference to the type of the own object. It was something like:
public interface I {
? getSelf();
}
public class A implements I {
A getSelf() {
return this;
}
}
public class B implements I {
B getSelf() {
return this;
}
}
I can't use an "I" where it's a "?", because I don't want to return a reference to the interface, but the class. I searched and found that there are no way to "self-refer" in Java, so I can't just substitute that "?" in the example for a "self" keyword or something like this. Actually, I came up to a solution that goes like
public interface I<SELF> {
SELF getSelf();
}
public class A implements I<A> {
A getSelf() {
return this;
}
}
public class B implements I<B> {
B getSelf() {
return this;
}
}
But it really seems like a workaround or something alike. Is there another way to do so?
There is a way to enforce using ones own class as a parameter when extending an interface:
interface I<SELF extends I<SELF>> {
SELF getSelf();
}
class A implements I<A> {
A getSelf() {
return this;
}
}
class B implements I<A> { // illegal: Bound mismatch
A getSelf() {
return this;
}
}
This even works when writing generic classes. Only drawback: one has to cast this to SELF.
As Andrey Makarov noted in a comment below this does not work reliably when writing generic classes.
class A<SELF extends A<SELF>> {
SELF getSelf() {
return (SELF)this;
}
}
class C extends A<B> {} // Does not fail.
// C myC = new C();
// B myB = myC.getSelf(); // <-- ClassCastException
Java supports covariant return types, so that's one option. Take advantage of the fact that both A and B are derived from Object:
public interface I {
Object getSelf(); // or I, see below
}
public class A implements I {
A getSelf() { return this; }
}
public class B implements I {
B getSelf() { return this; }
}
The point is that both A.getSelf() and B.getSelf() are legitimate overrides of I.getSelf(), even though their return type is different. That's because every A can be treated like an Object, and so the return type is compatible with that of the base function. (This is called "covariance".)
In fact, since A and B are also known to derive from I, you can replace Object by I for the same reasons.
Covariance is generally a Good Thing: Someone who has an interface object of type I can call getSelf() and get another interface, and that's all she needs to know. On the other hand, someone who already knows he has an A object can call getSelf() and will actually get another A object back. The additional information can be used to get a more specific derived type, but someone who lacks that information still gets everything that's prescribed by the interface base class:
I x = new A();
A y = new A();
I a = x.foo(); // generic
A b = y.foo(); // we have more information, but b also "is-an" I
A c = (A)x.foo(); // "cheating" (we know the actual type)
I was wondering if there are any other way to do so?
You can write it as follows:
public interface I {
I getSelf();
}
and then cast the result to the type you want. Your existing A and B classes will work as-is.
(This is an example of return type covariance. Support for return type covariance was added in Java 5. This approach will give compilation errors in older JDKs.)
The alternative version (you call it a work-around, but it isn't really) that uses generics allows you to avoid the explicit typecast. However, there is an implicit typecast in the generated code, and at runtime ... unless the JIT compiler can optimize it away.
There are no better alternatives, AFAIK.
As others have said, you can override the return type in the implementing classes:
public interface I {
public I getSelf();
}
public class A implements I {
#Override
public A getSelf() {
return this;
}
}
However, I have two 'why' questions for you:
1: Why do you want an Interface to return the implementing object? It seems to run against the general ideas of interfaces and inheritance to me. Can you show an example of how this might be used?
2: In any case, why would you want this function? If a.getSelf() == a, why not just use a?
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.