I have two parallel class hierarchies and I would like to convert objects from one to another. I can do it by manually specifying what conversion to do, but I need to specify the conversion twice: first when the actual conversion happens and second when I need to call it. Is there a way to specify it only once?
So here is the example, that works, but I would like to simplify. There are two convert functions that allow me to go between input classes (bI, cI) and output classes (bO, cO). This is unavoidable. The instanceof comparisons though bother me. Is there an elegant solution to avoid them?
public class ConversionTest {
static public class aI {}
static public class bI extends aI {}
static public class cI extends aI {}
static public class aO {}
static public class bO extends aO {}
static public class cO extends aO {}
// Convert from bI to bO.
private static aO convert(bI iVar) {return new bO();}
// Convert from cI to cO.
private static aO convert(cI iVar) {return new cO();}
public static void main(String argv []) {
// Input variable.
final aI iVar = new bI();
// Output variable.
final aO temp;
// Perform conversion.
if(iVar instanceof bI) {
temp = convert((bI)iVar);
} else if (iVar instanceof cI) {
temp = convert((cI)iVar);
}
}
}
I would like to do something like that:
final a0 temp = convert(iVar.getClass().cast(iVar));
But in this case, compiler complains that it can not find the proper convert function. Maybe I can specify an array of all possible conversions to try?
final a0 temp = convertHelp({bI,cI}, iVar);
I am not sure how I should implement this convertHelp function. It would iterate through the array and try to find the proper casting. Any suggestions?
Thanks.
Do you have access to the class implementations themselves? You could use polymorphism to make the conversion do the right thing if you stick it inside each class.
class ai
{
public ao convert()
{
return new ao();
}
}
class bi extends ai
{
#Override
public ao convert()
{
return new bo();
}
}
class ci extends ai
{
#Override
public ao convert()
{
return new co();
}
}
public static void main(String argv []) {
// Input variable.
final aI iVar = new bI();
// Output variable.
final aO temp = iVar.convert();
}
Given that you can't modify the input/output classes, the cleanest solution may be to use reflection:
class Converter {
public ao convert(ai iObj) {
final Method m = getClass().getDeclaredMethod("cvrt", iObj.getClass());
return (ao)m.invoke(this, iObj);
}
public ao cvrt(ai iObj) {
return new ao();
}
public bo cvrt(bi iObj) {
return new bo();
}
public co cvrt(ci iObj) {
return new co();
}
}
The implementation you already have is correct, and it's much prettier than what you'd get using the reflection APIs.
You can implement ConvertHelp; it would need to take an array of Class objects as parameter. But, again, the body of ConvertHelp would be very ugly.
What you are doing is against the ideals of a statically typed language. Java is not designed to make it easy - it's very easy to produce unsafe code this way.
private static aO convert(aI iVar) {
if (iVar instanceof bI)
return new bO();
if (iVar instanceof cI)
return new cO();
return new aO();
}
If you don't want your input classes to be dependent on the output classes, you can still benefit from polymorphism:
interface IFactory<T> {
public T createA();
public T createB();
public T createC();
}
class ai
{
public T convert(IFactory<T> f)
{
return f.createA();
}
}
class bi extends ai
{
#Override
public T convert(IFactory<T> f)
{
return f.createB();
}
}
class ci extends ai
{
#Override
public T convert(IFactory<T> f)
{
return f.createB();
}
}
class FactoryO extends IFactory<ao> {
public ao createA() {
return new ao();
}
public bo createB() {
return new bo();
}
public co createC() {
return new co();
}
}
To perform the conversion:
FactoryO f = new FactoryO();
ai ivar = // ...
ao ovar = ivar.convert(f);
Ideally, as suggested by the other posters, you should have a convert method on the input classes so that they can yield the output classes by themselves. If you want to have a parallel hierarchy of converters, your best recourse is to use the Visitor pattern.
You can define a ConverterVisitor interface and have two implementations as follows:
static public interface ConverterVisitor {
public aO convert(aI iVar);
}
static public class bIConverter implements ConverterVisitor{
public aO convert(aI iVar){
// requires a cast from aI to bI
return new bO();
}
}
static public class cIConverter implements ConverterVisitor{
public aO convert(aI iVar){
// requires a cast from aI to cI
return new cO();
}
}
But the bI and cI classes need to be modifiable as well which is not what you want to do.
Hence the only solution that remains is to use a ReflectionVisitor pattern.
This would involve writing a class that would fetch the corresponding converter using some kind of naming convention. In this case the converter's name is obtained using the convention of appending "Converter" to the class name. So a converter factory implementation may look like this:
static public class ConverterFactory {
public aO convert(aI ai) throws Exception {
return (aO) ((ConverterVisitor) Class.forName(ai.getClass().getName() + "Converter").newInstance()).convert(ai);
}
}
Very ugly! but it works!
The second alternative is to use some kind of registry in your factory.
Here is full listing. This is better since it uses generics to avoid multiple casts.
import java.util.HashMap;
import java.util.Map;
public class Trial {
static public class aI {}
static public class bI extends aI {}
static public class cI extends aI {}
static public class aO {}
static public class bO extends aO {}
static public class cO extends aO {}
static public interface ConverterVisitor<T extends aI> {
public aO convert(T iVar);
}
static public class bIConverter implements ConverterVisitor<bI>{
public bIConverter(ConverterFactory converterFactory){
converterFactory.register(bI.class, this);
}
public aO convert(bI iVar){
return new bO();
}
}
static public class cIConverter implements ConverterVisitor<cI>{
public cIConverter(ConverterFactory converterFactory){
converterFactory.register(cI.class, this);
}
public aO convert(cI iVar){
return new cO();
}
}
static public class ConverterFactory {
public Map<Class<?>,ConverterVisitor<?>>converterRegistry = new HashMap<Class<?>, ConverterVisitor<?>>();
public <T extends aI> void register(Class<T> clazz,ConverterVisitor<T> converter){
converterRegistry.put(clazz,converter);
}
#SuppressWarnings("unchecked")
public<T extends aI> aO convert(T ai) {
return ((ConverterVisitor<T>)converterRegistry.get(ai.getClass())).convert(ai);
}
}
public static void main(String argv []) throws Exception {
// Input variable.
final aI iVar = new bI();
// Output variable.
aO temp = null;
// the three lines below must be done in some generic place within the program.
ConverterFactory factory = new ConverterFactory();
new bIConverter(factory);
new cIConverter(factory);
temp = factory.convert(iVar);
System.out.println(temp);
}
}
Related
I'm reading a book "Thinking in Java" that states the following about inner classes:
Each inner class can independently inherit from an implementation. So one way to look at the inner class is as the rest of the solution of the multiple-inheritance problem. Interfaces solve part of the problem, but inner classes effectively allow "multiple implementation inheritance". That is, inner classes effectively allow you to inherit from more than one non-interface.
I've never used inner classes like that. So I started to thinking about how this could look and where this can be useful. I came up with this:
public class ReadWriteCollection {
public static void main(String[] args) {
var rw = new ReadWriteCollection();
var ro = rw.new ReadPart();
var ao = rw.new AddPart();
ao.add("foo");
System.out.println(ro.read(0));
}
private List<String> list = new ArrayList<>();
class AddPart extends AddOnlyCollection {
void add(String s) { list.add(s); }
}
class ReadPart extends ReadOnlyCollection {
String read(int index) { return list.get(index); }
}
public abstract static class ReadOnlyCollection {
final void someExistingImplementation(){ System.out.println("Foo"); }
abstract String read(int index);
}
public abstract static class AddOnlyCollection {
final void someExistingImplementation(){ System.out.println("Bar"); }
abstract void add(String s);
}
}
ReadOnlyCollection and AddOnlyCollection represent some existing implementations that I can't control. I've put them inside ReadWriteCollection just for convenience in my example.
So is it how inner classes should be used for "multiple implementation inheritance"? Can somebody give more examples and possible usages for this technique? Or is it the way inner classes were used in the past and no longer used like this (the book is quite old)?
I guess the idea of the author is the following to by-pass the multi inheritance restriction in Java:
public class A {}
public class B {}
public class C {}
public class MainTest {
private AA aa;
private BB bb;
private CC cc;
public static void main(String[] args) {
AA aa = new AA();
BB bb = new BB();
CC cc = new CC();
}
private static class AA extends A {
}
private static class BB extends B {
}
private static class CC extends C {
}
}
With that you have extended three different classes inside your MainTest.
I'm probably going about this in the most complicated way, but I'm hoping what I'm trying to do makes sense here.
Suppose I have some set of unrelated, generated classes and I want to Decorate them to create some kind of common API. So something like:
public abstract class GeneratedDecorator<T> {
private T generated;
public T getGenerated() { return generated; }
public void setGenerated(T generated) { this.generated = generated; }
public abstract String getString();
public static class ClassA extends GeneratedDecorator<GeneratedClassA> {
#Override
public String getString() { return getGenerated().getThisString(); }
}
public static class ClassB extends GeneratedDecorator<GeneratedClassB> {
#Override
public String getString() { return getGenerated().getADifferentString(); }
}
}
Now, to use this new fancy class I just say:
GeneratedDecorator.ClassA a = new GeneratedDecorator.ClassA();
a.setGenerated(myGeneratedInstanceA);
a.getString();
Ok so far so-so ... but now I want to manage an array of these Decorators.
So let's try:
public abstract class DecoratorBundle<T extends GeneratedDecorator> {
private static final int MAX_ROWS = 10;
private T[] bundle;
DecoratorBundle() { bundle = createBundle(); }
public String getString(int index) { return bundle[index].getString(); }
public void setRow(??? generated, int index ) {
//check index of bundle, if null create a new instance of appropriate type and set bundle[index] = new instance
//call setGenerated on instance at index
}
protected abstract T[] createBundle();
public static class ClassA extends DecoratorBundle<GeneratedDecorator.ClassA> {
#Override
protected GeneratedDecorator.ClassA[] createBundle() {
return new GeneratedDecorator.ClassA[MAX_ROWS];
}
}
public static class ClassB extends DecoratorBundle<GeneratedDecorator.ClassB> {
#Override
protected GeneratedDecorator.ClassB[] createBundle() {
return new GeneratedDecorator.ClassB[MAX_ROWS];
}
}
}
Here's where I'm stuck ... I want this DecoratorBundle to have a setRow(??? generated, int index) where the parameter is of the GeneratedDecorator's type (i.e, GeneratedClassA or GeneratedClassB). Seems like type erasure will probably make this impossible, but it would be really nice to have this DecoratorBundle class to completely manage it's bundle array. It currently is able to instantiate the array, but I want some way for it to create a new GeneratedDecorator-type and assign it in a setRow method.
If I'm going about this completely wrong then I would love to hear another idea.
I'm trying to convert following c# code and behavior to Java but I'm struggling to find the right syntax or programming pattern.
In c# I can use out like in interface IProxy<out Target> which allows me to implicitly cast IProxy<DerivedElement1> to IProxy<BaseElement> but for Java I'm not aware of any similar generic modifiers.
class BaseElement {
public static readonly Property<BaseElement> P1 = new Property<BaseElement>();
}
class DerivedElement1 : BaseElement {
public static readonly Property<DerivedElement1> P2 = new Property<DerivedElement1>();
}
class DerivedElement2 : BaseElement {
public static readonly Property<DerivedElement2> P2 = new Property<DerivedElement2>();
}
class Property<Owner> {
}
interface IProxy<out Target> {
}
class Proxy<Target> : IProxy<Target> {
}
class Program {
static void doSomething<Target>(IProxy<Target> proxy, Property<Target> property) {
// ...
}
static void Main(string[] args) {
Proxy<DerivedElement1> proxy1 = new Proxy<DerivedElement1>();
doSomething(proxy1, DerivedElement1.P1);
doSomething(proxy1, DerivedElement1.P2);
// expected error
doSomething(proxy1, DerivedElement2.P2);
}
}
It is very important that the expected error appears at compile time and not at run time.
Are you aware of any applicable syntax or pattern that would allow me to implement the same behavior without any additional casting?
I hope you can point me in the right direction, thank you much for your help!
I found out that I can use Proxy<? extends Target> to declare my proxy argument.
Here is the complete solution:
class BaseElement {
public static final Property<BaseElement> P1 = new Property<BaseElement>();
}
class DerivedElement1 extends BaseElement {
public static final Property<DerivedElement1> P2 = new Property<DerivedElement1>();
}
class DerivedElement2 extends BaseElement {
public static final Property<DerivedElement2> P2 = new Property<DerivedElement2>();
}
class Property<Owner> {
}
class Proxy<Target> {
}
class App {
static <Target>
void doSomething(Proxy<? extends Target> proxy, Property<Target> property) {
// ...
}
static void main(String[] args) {
Proxy<DerivedElement1> proxy1 = new Proxy<DerivedElement1>();
doSomething(proxy1, DerivedElement1.P1);
doSomething(proxy1, DerivedElement1.P2);
// expected error
doSomething(proxy1, DerivedElement2.P2);
}
}
If Ive got you correctly you should have a look at generic type in Java.
Sample Java Code
public class IProxy<T>{
....
}
public class Property<T>{
....
}
public class Program {
public static void doSomething(<IProxy<T> iProxy, Property<T> property){
......
}
}
Type Parameter Naming Conventions (not sure what Target is referring to in C#)
E - Element (used extensively by the Java Collections Framework)
K - Key
N - Number
T - Type
V - Value
S,U,V etc. - 2nd, 3rd, 4th types
I have generic class :
public class Test<T> {
private Test<? extends T> myInstance;
public Test<? extends T> getInstance () {
return myInstance;
}
public void setInstance (Test<? extends T> argType) {
this.myInstance = argType;
}
}
And I have two classes in my class hierarchy relations:
public abstract class Alphabet {
//code here
}
and
public class A extends Alphabet{
public A() {
super();
System.out.print("This is A call");
}
}
Finally I have a class where I want to store make generic class Test with particular type and set new Instance of Object -> A through setInstance() method:
public static void main(String[] args) {
List<Alphabet> list = new ArrayList<Alphabet>();
Test<Alphabet> tAlphabet = new Test<Alphabet>();
tAlphabet.setInstance(new A()); //Here is compilation ERROR
}
But I have got the compilation error in line tAlphabet.setInstance(new A());
What is the issue with my generic class?
Your instance is a Test object as it's currently written, and you are supplying it with an Alphabet object instead. You probably want your instance to be of type Alphabet:
public class Test<T> {
private T myInstance;
public T getInstance() {
return myInstance;
}
public void setInstance(T argType) {
myInstance = argType;
}
}
This way, your Test stores an Alphabet instead of another Test.
It seems you have made things more complicated than needed. You probably want this in your Test class instead of what you actually have:
private T myInstance;
public T getInstance () {
return myInstance;
}
public void setInstance (T argType) {
this.myInstance = argType;
}
With this arrangement you would be free to setInstance(new A()) on a Test<Alphabet> instance.
public class Test {
public static void main(String[] args) {
DemoAbstractClass abstractClass = new DemoAbstractClass() {
private String val;
#Override
public void runner() {
val = "test";
System.out.println(val);
this.run();
}
public String getVal() {
return val;
}
};
abstractClass.runner();
/**
* I want to access getVal method here
*/
}
}
abstract class DemoAbstractClass {
public void run() {
System.out.println("running");
}
public abstract void runner();
}
Here, I'm declaring an abstract class DemoAbstractClass. I can obviously create a new class that extends this class and add this method to it. But, I would prefer not doing that in my scenario.
Is there any other way to access getVal method in above code??
You can't. You need to make a proper (non-anomous) class out of it. Make it an inner private class if you want to limit its scope.
Alternatively, you could use a StringBuffer and share a referense to it between the methods. Not extremely clean however.
Related question:
Accessing inner anonymous class members
Short of using reflection, you cannot as you have no access to the concrete type of the object to be able to bind the methodcall to
If you don want to do something like this in a sane manner, declare a named class and use that as the type of abstractClass
Unfortunately, if you cannot name the type, you cannot access the methods at the language level.
What you can do, though, is use the reflection API to get a Method object and invoke it on this object.
This, however, is pretty slow. A private class or private interface would be much faster.
I can obviously create a new class that extends this class and add this method to it.
You've already done this; the end result was an anonymous inner class: new DemoAbstractClass() { ... }; If you just moved that declaration into its own class -- you can even make it a private class -- you can access getVal.
Per your example above:
public class Test {
public static void main(String[] args) {
DemoClass abstractClass = new DemoClass();
abstractClass.runner();
/**
* I want to access getVal method here
*/
abstractClass.getVal(); // can do this here now
}
private class DemoClass extends DemoAbstractClass {
private String val;
#Override
public void runner() {
val = "test";
System.out.println(val);
this.run();
}
public String getVal() {
return val;
}
}
}
}
Another option is to make a StringBuilder a member of the main method and use the closure nature of anonymous inner methods:
public static void main(String[] args) {
final StringBuilder value = new StringBuilder();
DemoAbstractClass abstractClass = new DemoAbstractClass() {
#Override
public void runner() {
value.append( "test" );
System.out.println(val);
this.run();
}
};
abstractClass.runner();
// use val here...
String val = value.toString();
}