class contains one element of subclasses - java

Giving the diagram below, I want to know the following:
How to make sure that a class car can have a GPS of type A or B not both?

Because of the max multiplicity of 1, all your example diagram is missing is a generalization set that is {complete, disjoint}. Your diagram now says {incomplete, overlapping}, by default, which means an instance can be a member of both A and B, or just a member of GPS.

What about using generics like this:
public class A<T extends B> {
List<T> list = new ArrayList<>();
public List<T> getList() {
return list;
}
public void setList(List<T> list) {
this.list = list;
}
}
public class B {
}
public class C extends B {
}
public class D extends B {
}
Then you will instantiate class A with the desired subtype of B like this:
A<C> a = new A<>();
C c = new C();
D d = new D();
a.getList().add(c); //works fine
a.getList().add(d); //compile error

Taking the fruit basket from your comment, you need to specify a multiplicity for 0..n instead of the 1.
If you want all instances to be the same subclass you need to add a constraint in any way. If your tool does not permit it, just add a note with { all instances ofBmust have the same type } or the like.

Related

How to use Constructors/Casting with Generic Types

I have a parent class, Parent, with two child classes, A and B. I have another class, Wrapper<Type1,Type2>, that contains an interface, Function<Type1,Type2>, which is supposed to transform an A into a B or a B into an A.
If I define
new Wrapper<A,B>(new Function<A,B>(){public B transform(A a){return new B(a);}});
outside of the Wrapper class, then this works fine.
I run into the problem that I can't instantiate a generic type when I want to define a default Function for the default constructor public Wrapper() within the Wrapper<Type1,Type2> class itself.
Eclipse recommends casting from Type1 to Type2, but the problem is that A can't cast to B because they are sibling classes. I do have constructors for Parent(Parent), A(B), and B(A), so it would be great if I could implement a generic constructor somehow. How can I work around this?
public class Parent {
protected int value = 0;
public void setValue(int x){ value = x; }
public int getValue(){ return value; }
public Parent(){}
public Parent(A a){setValue(a.getValue());}
public Parent(B b){setValue(b.getValue());}
public Parent(Parent p){setValue(p.getValue());}
}
public class A extends Parent{
public A(){ setValue(1); }
public A(B b){ setValue( b.getValue()); }
}
public class B extends Parent{
public B(){ setValue(2); }
public B(A a){ setValue(a.getValue()); }
}
public interface Function <Type1 extends Parent, Type2 extends Parent> {
public Type2 transform(Type1 t);
}
public class Wrapper<Type1 extends Parent, Type2 extends Parent> {
Function<Type1,Type2> function;
public Wrapper(Function<Type1,Type2> x){ function = x; }
public Wrapper(){
function = new Function<Type1,Type2>(){
public Type2 transform(Type1 t){
///I want to use constructor Type2(t), given that they both extend Parent
//return new Type2( t);
return (Type2) t; ///causes an error because can't cast from A to B
}
};
}
public Type2 transform(Type1 t){
return function.transform(t);
}
}
public class Main {
public static void main(String[] args){
///Start with custom function. This part works.
Wrapper<A,B> wrapper = new Wrapper<A,B>(
new Function<A,B>(){
public B transform(A a){
///Want to use constructor B(a)
///Can't cast A to B
return new B(a);
}
}
);
A a = new A();
B b = wrapper.transform(a);
///This part works
System.out.println(b.getValue());
///Next try the default Function
wrapper = new Wrapper<A,B>();
b = wrapper.transform(a); ///This part causes the error, as wrapper attempts to cast from A to B
System.out.println(b.getValue());
}
}
Edit:
My question is unique in scope and implementation from the suggested duplicate. E.g., the structure of my code is a simple parent with two sibling child classes. The structure in the possible duplicate is more intricate, involving multiple generations and child classes that are disheveled in a confusing way. I'm not sure what that code is attempting to do, and the answer didn't help me understand my own question in the slightest as it seemed particular to the distinct structure of the other question.
There's no way to make a "generic" constructor. The solution closes to your current implementation is to instantiate objects in your function. As this is anyway the responsibility of the caller (in your design), then it's easy:
Wrapper<A, B> wrapper = new Wrapper<A, B>((a) -> new B(a));
But where the default Wrapper() constructor is being called, you can make the caller send Class objects for type1 and type2:
public Wrapper(Class<Type1> type1Class, Class<Type2> type2Class) {
this.function = (object1) -> {
try {
return type2Class.getConstructor(type1Class).newInstance(object1);
} catch (Exception e) {
throw new RuntimeException(e);
}
};
}
With both of the above, your main method will look like the following:
public static void main(String... args) {
Wrapper<A, B> wrapper = new Wrapper<A, B>((a) -> new B(a));
A a = new A();
B b = wrapper.transform(a);
System.out.println(b.getValue());
wrapper = new Wrapper<A, B>(A.class, B.class);
b = wrapper.transform(a);
System.out.println(b.getValue());
}
And this runs without any type cast errors.
The java1.7 version of the above lambda expressions:
Wrapper<A, B> wrapper = new Wrapper<A, B>(new Function<A, B>() {
#Override
public B transform(A a) {
return new B(a);
}
});
And:
this.function = new Function<Type1, Type2>() {
#Override
public Type2 transform(Type1 object1) {
try {
return type2Class.getConstructor(type1Class).newInstance(object1);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
Since it's not possible to create an instance using a generic type parameter we must work around it. I'll restrict the answer to Java 7 as I read from the comments you're working with. Here is my suggestion:
public interface Transform<P extends Parent> {
P with(int value);
}
public static void main(String[] args) {
Transform<B> transformToB = new Transform<B>() {
#Override
public B with(int value) {
return new B(value);
}
};
A a = new A();
B b = transformToB.with(a.getValue());
System.out.println(b.getValue());
}
How it works?
We have an interface Transform<P extends Parent> defining the method with. This method has one parameter. This is the only one field of the classes you defined. Using this value the method has to return an instance of some P which extends Parent. Looking at the implementation of transformToB it creates a B instance by calling the (by me added) constructor B(int value).
Why another constructor?
Declaring constructors like B(A a) or A(B b) results in a circular dependency between these classes. A and B aren't loosely coupled. Declaring a constructor which takes only a value we instantiate the state without having to know where this value comes from.
Also declaring constructors like Parent(A a) and Parent(B b) introduces dependencies to Parent on it's subclasses. Following this approach Parent would need to provide a constructor for each subclass.
Possible extension:
If value is just an example for many other fields, we do not want to define a constructor like A(int value1, int value2, String value3, ...) having many parameters. Instead of we could use the default constructor A() and do the transformation like this:
interface Transform<From extends Parent, To extends Parent> {
To from(From f);
}
public static void main(String[] args) {
Transform<A, B> transformToB = new Transform<A, B>() {
#Override
public B from(A a) {
B b = new B();
b.setValue(a.getValue());
b.setValue2(a.getValue2());
b.setValue3(a.getValue3());
return b;
}
};
A a = new A();
B b = transformToB.from(a);
System.out.println(b.getValue());
}
This last approach is also applicable if A and B have different fields. In case B has a field String value4 we could add an additional line to transformToB like b.setValue4(a.getValue3()+"#"+a.getValue2());.

Polymorphic method return type down-casting in java

So I don't know if this is possible I've tried searching it but maybe my search terms are off. Basically I'm wondering, is there a way to create a generic function/method in a super class that returns the downcast object.
class A {
public <downcasted type (in this example B if called from a B instance)> test() {
return this;
}
}
class B extends A { }
B b = new B().test()
basically having "test()" return the B instance as type B even know the function/method is declared purely in the parent class?
I know I can cast the variable, tho having many functions some of which may return Lists of the class type, etc become troublesome. I also realize I could #override the function in B and do a "return (B)this.super()" thing, but again wrapping many functions is tedious and makes makes updating the base classes code more painful.
I also know you can do
"class A<T extends A>"
and then define B as
"class B extends A<B>"
but then if you want to make a "C" that extends "B" it breaks.
So is this type of behavior possible? If so, what is it called and how do I implement it?
An example as to where this behavior could be useful would be any base data structures you want to make extendable like an N-Ary Tree that you extend into oct/quad tree structure and/or an extended class that adds a "Name" and "Attributes" or something for a xml-like node.
Edit:
This seems to work(as far as the linter is concerned), it's a bit more work to implement the base methods but it's got the desired end result as far as I can tell. That said when I attempt to run it, it gives me a "cannot find symbol: class type" error. :S
static class D extends auto {
final Class type = getClass();
#SuppressWarnings("unchecked")
public <T extends type> T test() {
return (T)type.cast(this);
}
}
static class E extends D { }
static class F extends E { }
static {
D d = new D().test();
E e = new E().test();
F f = new F().test();
}
Update
There is a simpler way, which seems to work:
class Alpha {
#SuppressWarnings("unchecked")
<T extends Alpha> T test() {
return (T) this;
}
}
class B extends A { }
However, that does not support method chaining.
Original post
You need test() to return a subtype of A, rather than A itself. In order to do this, the signature of the A class could be this:
class A<T extends A<?>> {
#SuppressWarnings("unchecked")
public T test() {
return (T) this;
}
}
If you create a class B extending A, you will need B.test() to return an instance of B, without needing to override test() returning a specific type. You could then do something like this:
class B<T extends B<?>> extends A<T> { }
Now T is a subclass of B, and because test()'s return type is T, it will return a B instance. Further subclassing can be done in the same way:
class C<T extends C<?>> extends B<T> { }
And statements like this will work:
C<?> c = new C<>().test();

How to do different things with subclasses based on subclass type with using instanceof?

I have an abstract class A and two subclasses B and C.
In some other class I have a list of instances of A's ie: List. The list of A's could of course contain elements that could be instances of B or C.
If the instance is B, I want to add it to table A which resides in Class D.
If the instance is C, I want to add it to table B which also resides in Class D.
Is this possible without using instanceof?
Yes, put a method in A which you override in B and C containing the table name.
You have a list L : List<A> which contains B extends A and C extends A. While you fetch elements E from L you like to add E to D.A if E instanceof B or add E to D.B if E instanceof C.
Use the Visitor Pattern by providing an abstract method A.visit(D). B.visit(D) would implement it by calling D.addMeToTableA(this) while C.visit(D) would implement it by calling D.addMeToTableB(this).
Here could be a solution:
public abstract class A {
public abstract void addTo(D d);
}
public class B extends A {
#Override
public void addTo(D d) {
d.addB(this);
}
}
public class C extends A {
#Override
public void addTo(D d) {
d.addC(this);
}
}
A simple D class:
public class D {
public void addB(B b) {
// ...
}
public void addC(C c) {
// ...
}
}
Then:
List<A> list = new ArrayList<A>();
list.add(new B());
list.add(new C());
D d = new D();
for (A a : list) {
a.addTo(d);
}
A possible approach is to let B and C return some discriminator to let the class that moves stuff from the list into D's tables know to which table they should be added, but you'll eventually get to a point where you need a switch or something like that.
Example:
public enum TypeOfA { TYPE_1, TYPE_2 }
public abstract class A {
// your other stuff
public abstract TypeOfA getType();
}
public class B extends A {
public TypeOfA getType() {
return TypeOfA.TYPE_1;
}
}
public class Sorter {
public void putInTables() {
for (final A a: this.listOfAs()) {
this.getTableFor(a).add(a);
}
}
private Table getTableFor(final A a) {
switch(a.getType()) {
case TypeOfA.TYPE_1: return tableA;
case TypeOfA.TYPE_2: return tableB;
}
}
}
With this solution, you could add more sub-classes of A that share the same type of "discriminator" with B or C, so your sorter class will put their instances in the same tables.
Apart from that, you keep the actual decission in the Sorter's logic, and if TYPE_1 and TYPE_2 have some semantic meaning, B and C don't actually have to know why they expose it.
"How to do different things with subclasses based on subclass type", or in other words: polymorphism. Off course is possible, its one of the main principles of OO software. And you don't need to use instanceOf, .getClass or others forms of meta-programing for solving a basic OO problem.
You can have an abstract method in A like:
public String belongsToTable() {}
in A you implement in one way in B you implement in another way.
Off course its probably a bad name and off course returning a string is probably a bad idea, its only an example based in your A,B,C problem. Software development its about naming and semantic, the next time please use meaningful names if you really want good advice and no a generic advice that you can find in a basic OO book.

How to parse a generic type through several levels of extends?

I have the following 3 classes:
public class MyClass1<T extends MyClass1> {
private List list = new ArrayList();
public T add(Object... o) {
Collections.addAll(this.list, o);
return (T) this;
}
public MyClass2 two() {
MyClass2 n = new MyClass2();
add(n);
return n;
}
}
public class MyClass2<T extends MyClass2> extends MyClass1<MyClass2> {
public MyClass3 three() {
MyClass3 n = new MyClass3();
add(n);
return n;
}
}
public class MyClass3<T extends MyClass3> extends MyClass2<MyClass3> {
}
I want to call the methods in a chain. Like this:
MyClass1 m1 = new MyClass1();
m1.add(1).add(2).two().add(3).three().add(4);
For some reason add(3) returns MyClass1, where I would have expected it to return MyClass2. If I remove <T extends MyClass2> from MyClass2, add(3) returns MyClass2 as desired, but then MyClass3 cannot extend MyClass2 with a type.
How can I make this work, so I can chain all my methods and still use the add(Object...) method from all my classes?
UPDATE:
The above is clearly an example. What I'm really trying to create here is a simple tool for building MySQL queries. I have a lot of EJB3 entities that already define my table and column names, but need to make a few native queries, because some things just cannot be achieved with EJB-QL. Yet, I don't want to have to specify table and column names more than once in my code, and therefore need a tool that can create a native MySQL query using EJB3 entities. When I use the code I've created, it might look like this:
new Query().select().field(MyEntity_.id).field(MyEntity_.name).field(MyOtherEnt_.type);
Or:
new Query().join().left(MyOtherEnt_.myEntityId);
Here I might have a Query object, which specifies some generic MySQL syntax and then extend it. It could be something like this: Query > extended by Select > extended by SubQuery. The whole thing is customized to the specific project I'm working on.
add(3) returns MyClass1 because method add is member of class MyClass1. You would have to override add method in your extending classes in order to return different datatype.
The definition of MyClass2 should be more or less like that
class MyClass2<T extends MyClass2> extends MyClass1<MyClass2> {
#Override
public T add(Object... o) {
super.add(o);
return (T)this;
}
public MyClass3 three() {
MyClass3 n = new MyClass3();
add(n);
return n;
}
}
anyway, I dont know what are you trying to achieve, but IMHO you have took bad approach. Moreover you are not declaring types T when you are creating new parametrized objects, so all in all, for compiler and JRE everything here is just of Object type.
Your biggest problem is that your're extending raw types. Change:
public class MyClass1<T extends MyClass1> {
to
public class MyClass1<T extends MyClass1<T>> {
Once you use a raw type, all generic info is stripped from the class.
Similar for the other classes.
For now I've decided to make it a little more simple and have MyClass3 extend MyClass1 instead of MyClass2. If I keep it at "2 levels", it works, so I'll just have to live with the constrain that MyClass3 cannot extend MyClass2, if I want to be able to chain the methods from MyClass1. My code then looks like this:
public class MyClass1<T extends MyClass1> {
private List list = new ArrayList();
public T add(Object... o) {
Collections.addAll(this.list, o);
return (T) this;
}
public MyClass2 two() {
MyClass2 n = new MyClass2();
add(n);
return n;
}
}
public class MyClass2 extends MyClass1<MyClass2> {
public MyClass3 three() {
MyClass3 n = new MyClass3();
add(n);
return n;
}
}
public class MyClass3 extends MyClass1<MyClass3> {
public void four() {}
}
And I can write:
MyClass1 m1 = new MyClass1();
m1.add(1).add(2).two().add(3).add(4).three().add(5).add(6).four();

Java Generics, return generic extending

Why am i not allowed to do this?
public abstract class A {}
public class B extends A {}
...
public ArrayList<A> foo()
{
return new ArrayList<B>();
}
I changed to public since there are so many people that love to point stupid errors.
Why should i have to write ALL this code. Just to satisfy Java's non-senses?
public List<A> foo()
{
List<A> aList = new ArrayList<A>();
List<B> bList = new ArrayList<B>();
/* fill bList*/
for (B b : bList)
{
aList.add(b);
}
return aList;
}
An ArrayList<B> is not an ArrayList<A>. You can't add any arbitrary A into it, for example. Or as I like to think of it: a bunch of bananas isn't a fruitbowl. When you try to add an apple to a bunch of bananas, it rolls off...
You can use wildcards to make it work though:
public ArrayList<? extends A> foo()
{
return new ArrayList<B>();
}
See the Java Generics FAQ for more details.
EDIT: To answer your specific question of why you need to write all that extra code: you don't. Just create an ArrayList<A> within foo() to start with. There's no need to copy the contents of one list to another.
If you still object to Java's behaviour, what would you want to happen with the following code?
// Doesn't compile, fortunately...
List<String> strings = new List<String>();
List<Object> objects = strings;
objects.add(new Date());
String string = strings.get(0); // Um, it's a Date, not a String...
a) For one thing, function does not exist in Java. Java methods have the format
modifiers <type_parameters[,type_parameter]*>? return_type method_name (
[parameter[,parameter]*]?
) [throws exceptiontype[, exceptiontype]*]{ method_body }
b) Here's how to do it:
public List<? extends A> foo()
{
return new ArrayList<B>();
}
c) I changed the method signature to List. It's bad practice to have implementation types in your class' external API if an appropriate interface exists.
because ArrayList<B>() is not ArrayList<A>. it is not extended from it
B extends A doesn't mean ArrayList<B>() extends ArrayList<A>()

Categories