I have 3 objects (let them be object a of class A, object b of class B and object c of class C) and I need to combine them to a single instance of java.lang.Object (let it be o). So in the end object o will contain inside it the three objects mentioned above. Any ideas on how this one can be achieved?
Do you mean something like this?
public class Triplet<A, B, C> {
private final A a;
private final B b;
private final C c;
Triplet(A a, B b, C c){
this.a = a;
this.b = b;
this.c = c;
}
}
public class MyClassA {}
public class MyClassB {}
public class MyClassC {}
public class Main {
public static void main(String[] args){
Object o = new Triplet<>(new MyClassA(), new MyClassB(), new MyClassC());
}
}
For getter , no issues you can return the current array
for setter , you can use the Collections algorithm addAll for exemple :
String[] values = { "cat", "dog", "bird" };
setArray(values);
public void setArray(String[] sourceArray){
ArrayList<String> list = new ArrayList<>();
list.add("elephant");
Collections.addAll(list, values);
}
Related
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());.
I have a base class with a method called execute :
class A {
public execute(int a){}
}
I also have a class B, which extends A, but the execute method needs more parameters:
Currently, my solution is using optional parameters :
class B extends A {
public execute(int a, Object... parameters){
long b = (long)parameters[0];
boolean c = (boolean)parameters[1];
....
}
}
This would still be ugly because I must cast on parameters. Are there other options for this situation?
you can add an execute(int a, int b) in B, but it won't override the execute(int a) method, it will overload it. Both method will be callable on an instance of B.
This would break the OO paradigm. The L in solid stands for Liskov substitution principle.
The principle applied for you example is that B should behave as A.
A better solution would be to injects those parameters via the constructor and have an execute without any parameters.
class A {
int a;
public A(int a){
this.a = a;
}
public execute(){ // do something with a}
}
class B {
int a;
long b;
boolean c;
public B (int a, long b, boolean c) {
this.a = a;
this.b = b;
this.c = c;
}
public execute(){ // do something with a, b and c}
}
I have got started with Java Generics. in the below class, as the class is holding T, I want to have also a class which can extend T. Please help.
public class HolderUnique<T> {
private T a;
public HolderUnique(T a){
this.a = a;
}
public T getA() {
return a;
}
public void setA(T a) {
this.a = a;
}
}
Let's say you have a class S, which extends T, and you have also declared hold as a HolderUnique<T>. Let's also say you have declared sObj as type S. There is absolutely no reason why you cannot say T.setA(sObj).
I've got two methods with the same list and types of arguments and almost the same body but each of them calls another function to fetch list of elements. To be more precise:
public void method1 (int a, int b) {
//body (the same in both of methods)
List<SomeObject> list = service.getListA(int c, int d);
//rest of the body (the same in both of methods)
}
public void method2 (int a, int b) {
//body (the same in both of methods)
List<SomeObject> list = service.getListB(int c, int d, int e);
//rest of the body (the same in both of methods)
}
What is the best approach to the problem avoiding code duplication in that case? I thought about Strategy pattern, but there is a problem with difference in argument list.
UPDATE:
public void method1 (int a, int b) {
//body (the same in both of methods)
int c = some_value;
List<SomeObject> list = service.getListA(a, b, c);
//rest of the body (the same in both of methods)
}
public void method2 (int a, int b) {
//body (the same in both of methods)
int c = some_value;
int d = another_value;
List<SomeObject> list = service.getListB(a, b, c, d);
//rest of the body (the same in both of methods)
}
So some variables are local and some are passed through arguments.
Factor them out into additional methods.
public void method1 (int a, int b) {
MyClass myClass = method3(a, b);
List<SomeObject> list = service.getListA(myClass.getC(), myClass.getD());
method4(list);
}
public void method2 (int a, int b) {
MyClass myClass = method3(a, b);
List<SomeObject> list = service.getListB(myClass.getC(), myClass.getD(), myClass.getE());
method4(list);
}
public MyClass {
private final int c;
private final int d;
private final int e;
...
}
public MyClass method3(int a, int b) {
// body
return new MyClass(c, d, e)
}
public void method4(List<SomeObject> list) {
// rest of body
}
One way of avoiding code duplication in your case could be to introduce an extra parameter that is used to decide which method to retrieve the list is going to be used:
public void method (int a, int b, int method) {
//body (the same in both of methods)
List<SomeObject> list = null;
switch (method) {
case 1:
list = service.getListA(int c, int d);
break;
case 2:
list = service.getListB(int c, int d, int e);
break;
}
//rest of the body (the same in both of methods)
}
instead of using int method as the additional parameter I would use an new enum type and define a default case in the switch statement.
Encapsulate the invocation of service.getListA or service.getListB in an ListSource class/interface, implement each version in concrete classes and pass a concrete instance as a third argument. This is basically the object-oriented version of the answer proposed by jlordo.
interface ListSource {
List<SomeObject> getList(int c, int d, int e);
}
class ListSourceA implements ListSource {
// constructor etc.
#Override
public getList(int c, int d, int e) {
return service.getListB(c, d);
}
}
class ListSourceB implements ListSource {
// constructor etc.
#Override
public getList(int c, int d, int e) {
return service.getListA(c, d, e);
}
}
public void method (int a, int b, ListSource source) {
//body (the same in both of methods)
List<SomeObject> list = source.getList(int c, int d, int e);
//rest of the body (the same in both of methods)
}
public void method (int a, int b, List<SomeObject> theList) {
//body (the same in both of methods)
List<SomeObject> list = theList;
//rest of the body (the same in both of methods)
}
This to me removes ALL the code duplication, means the method NEVER has to be modified each time we want to operate on a list derived using a different method signature.
I believe you could further this if the type SomeObject is not known using generics i.e. (and I am not a java programmer so you will have to read the docs)
public void method (int a, int b, List<T> theList) {
//body (the same in both of methods)
List<T> list = theList;
//rest of the body (the same in both of methods)
}
You could also use an enum:
public void method(int a, int b, Service service) {
// body
List<SomeObject> list = service.getList(myClass);
// rest
}
public enum Service {
METHOD_1 {
#Override
public List<SomeObject> getList(MyClass myClass) {}
},
METHOD_2 {
#Override
public List<SomeObject> getList(MyClass myClass) {}
};
public abstract List<SomeObject> getList(MyClass myClass);
}
public MyClass {
private final int c;
private final int d;
private final int e;
...
}
Essentially the same as #proskor except in a different form.
If the body parts depend upon one another so you can't do as #dicarlo2's answer:
private interface GetObjects {
List<SomeObject> get();
}
public void method1(int a, int b) {
impl(a, b, new GetObjects() { public List<SomeObject> get() {
return service.getListA(c, d);
}});
}
public void method2(int a, int b) {
impl(a, b, new GetObjects() { public List<SomeObject> get() {
return service.getListB(c, d, e);
}});
}
private void impl(int a, int b, GetObjects getObjects) {
//body (the same in both of methods)
List<SomeObject> list = getObjects.get();
//rest of the body (the same in both of methods)
}
You can use an enum in place of GetObjects if you are concerned about the new, but don't mind getting the order mixed up, missing out on outer this and don't want to open this up (although it could implement an public interface).
Better syntax coming in Java SE 8, possibly. IIRC, along the lines of:
public void method1(int a, int b) {
impl(a, b, { -> service.getListA(c, d) });
}
Suppose I have two classes CLassA and CLassB. And they have one atributte in common, for example the number of elements that each class holds.
How can i create a collection from objects of ClassA and CLassB and sort by that attribute (ascending of descending order, doesn't matter)?
I made a collection of type but when I try to implement the Comparable Interface i can't acess to that method (a get that returns the nr of elements for example).
What solutions do I have?
Thanks for your help!
You could make a custom java.util.Comparator and sort using the Collections.sort(List list,
Comparator c) method.
Really ClassA and ClassB should be related either through an inheritance hierarchy, or by a common interface if you are going to put them both in the same collection.
The simplest thing would be to have a common interface that provides an accessor method for the common attribute. And then the comparator could use that method (through the interface) for fetching the value from ClassA's instance as well as ClassB's instance.
Hmm.. is it possible for ClassA and ClassB to share an interface?
interface InterfaceZ
{
int getCount();
}
class ClassA implements InterfaceZ
{
int getCount() { return _myArray.length; }
}
class ClassB implements InterfaceZ
{
int getCount() { return _complexCollection.size(); }
}
Then just sort the list like so:
List<InterfaceZ> myArray;
... fill up array ...
Collections.sort(myArray, new Comparator<InterfaceZ>() {
public int compare(InterfaceZ o1, InterfaceZ o2) {
return o2.getCount() - o1.getCount();
}});
If you have access to the declaration of CLassA and ~B, then go with a common interface, if not you could write a Wrapper for both Classes:
I defined - against the description - my own classes ~A and ~B, to have something to test. Imagine they're foreign source, and you just have access to the classes.
import java.util.*;
public class SortAB
{
class CLassA {
int [] elements;
public CLassA (int [] a) {elements = a;}
public int getElementCount () {return elements.length;}
}
class CLassB {
List <Integer> elements;
public CLassB (List <Integer> l) {elements = l;}
public int getElementCount () {return elements.size ();}
}
/** a common element-count-wrapper with compareTo method */
abstract class EcWrapper <T> implements Comparable <EcWrapper> {
public abstract int getElementCount ();
public int compareTo (EcWrapper o) {return getElementCount () - o.getElementCount ();}
}
/** concrete Wrapper for CLassA */
class EcAWrapper extends EcWrapper <CLassA> {
private CLassA inner;
public EcAWrapper (CLassA t) {
inner = t;
}
public int getElementCount () {return inner.getElementCount (); }
}
/** concrete Wrapper for CLassB */
class EcBWrapper extends EcWrapper <CLassB> {
private CLassB inner;
public EcBWrapper (CLassB t) {
inner = t;
}
public int getElementCount () {return inner.getElementCount (); }
}
// testing
public SortAB ()
{
int [] ia = {3, 5, 7, 6, 9, 11, 14};
List <Integer> il = new ArrayList <Integer> ();
for (int i: ia)
il.add (i);
il.add (15);
il.add (16);
CLassA a = new CLassA (ia);
CLassB b = new CLassB (il);
List <EcWrapper> list = new ArrayList <EcWrapper> ();
list.add (new EcBWrapper (b));
list.add (new EcAWrapper (a));
show (list);
Collections.sort (list);
show (list);
}
public static void main (String args[])
{
new SortAB ();
}
public static void show (List <EcWrapper> list)
{
for (EcWrapper e: list)
System.out.println ("\t" + e.getElementCount ());
System.out.println ("---");
}
}