public abstract class Parent {
private Parent peer;
public Parent() {
peer = new ??????("to call overloaded constructor");
}
public Parent(String someString) {
}
}
public class Child1 extends parent {
}
public class Child2 extends parent {
}
When I construct an instance of Child1, I want a "peer" to automatically be constructed which is also of type Child1, and be stored in the peer property. Likewise for Child2, with a peer of type Child2.
The problem is, on the assignment of the peer property in the parent class. I can't construct a new Child class by calling new Child1() because then it wouldn't work for Child2. How can I do this? Is there a keyword that I can use that would refer to the child class? Something like new self()?
I'm not sure if it is possible to do this without running into cycles. I am convinced that it would be a lot clearer to write this using factory methods instead of constructors.
public abstract class Parent implements Clonable{
private Object peer;
// Example 1
public Parent() {
try {
peer = this.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
// Example 2
public Parent(String name) {
try {
peer = this.getClass().getConstructor(String.class).newInstance(name);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public <T extends Parent> T getPeer() {
return (T)peer;
}
}
public class Child01 extends Parent { }
public class Child02 extends Parent { }
It seems that the code may be more simple.
I'll start by saying that I think it's probably a really bad design. And the class names are also bad, but I'll stick with them.
However, one way of dealing with it:
public abstract class Parent {
interface PeerFactory {
Parent create(Parent peer);
}
private final Parent peer;
protected Parent(Parent peer) {
super();
this.peer = peer;
}
protected Parent(PeerFactory peerFactory) {
super();
this.peer = peerFactory.create(this);
}
}
public class Child1 extends parent {
private static final PeerFactory peerFactory = new PeerFactory {
public Parent create(Parent peer) {
return new Child1(peer);
}
};
public Child1() {
super(peerFactory);
}
private Child1(Peer peer) {
super(peer);
}
}
Something like this:
public class Peer {
public static abstract class Parent {
private Parent peer;
protected Parent(boolean needPeer) {
if (needPeer) {
try {
peer = getClass().newInstance();
}
catch (Throwable e) {
System.err.println(e);
}
}
}
public String getPeerClass() {
return peer.getClass().toString();
}
}
public static class Child1 extends Parent {
public Child1() {
this(false);
}
public Child1(boolean needPeer) {
super(needPeer);
}
}
public static class Child2 extends Parent {
public Child2() {
this(false);
}
public Child2(boolean needPeer) {
super(needPeer);
}
}
public static void main(String[] args) {
Parent p1 = new Child1(true);
Parent p2 = new Child2(true);
System.out.println(p1.getPeerClass());
System.out.println(p2.getPeerClass());
}
}
This one works with default constructor, there's a bit more trickery involved if you want to construct a new peer with a non-default constructor. See The javadoc for Class.
Edit: fixed the infinite recursion :)
Note that without an accessor in the parent class you cannot get the peer object (you cannot instantiate Parent), so this design only makes sense as concept proof.
I would suggest replacing this whole thing with a Factory pattern, where you have complete control over what gets a peer added and you don't have to do it in the constructor.
Replying for answer of Leonid Kuskov
Your example 2 will always throw a StackOverflowException. I fiddled around with the code a bit an below is the correct implementation for that. Though thanks to you to give me pointers in that direction.
public class AbstractClassDemo {
public static void main(String[] args) {
Child1 c1 = new Child1();
System.out.println(c1.getPeer().getClass().getName());
}
}
abstract class Parent {
private Object peer;
public Parent() {
}
public Parent(String s) {
try {
setPeer(this.getClass().getConstructor(String.class)
.newInstance(""));
} catch (Exception e) {
e.printStackTrace();
}
}
public Object getPeer() {
return peer;
}
public void setPeer(Object peer) {
this.peer = peer;
}
}
class Child1 extends Parent implements Cloneable {
public Child1() {
super("Child1");
}
public Child1(String child1) {
}
}
class Child2 extends Parent implements Cloneable {
public Child2() {
super("Child2");
}
public Child2(String child2) {
}
}
public abstract class Parent implements Clonable {
private Object peer;
// Example 1
public Parent() {
try {
peer = this.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
// Example 2
public Parent(String name) {
try {
peer = this.getClass().getConstructor(String.class).newInstance(name);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public <T extends Parent> T getPeer() {
return (T)peer;
}
public class Child01 extends Parent { }
public class Child02 extends Parent { }
public abstract class Parent {
private Parent peer;
public Parent(Parent peer) {
this.peer = peer;
}
public Parent(String someString) {
}
}
public class Child1 extends parent {
public Child1() {
super(new Child1())
}
}
public class Child2 extends parent {
public Child2() {
super(new Child2())
}
}
Here's the simplest way I can think of. You could probably do it in the parent class using some of the java reflection API though (so ask the 'this' reference what class it is and construct a new class of that type. It may not work depending on how java constructors work though. In C++, the 'this' pointer in a constructor is of the same type as the constructors class)
Related
I'm writing a custom rule that will check whether the class under analysis is extending a type.
For example:
class Bus {
}
class Transport {
}
class PublicTransport extends Transport {
}
class Bus should extend class Transport or a sub class of Transport.
public class EnsureSuperClassRule extends IssuableSubscriptionVisitor {
final String SUPER_CLASS = "common.service.SuperService";
#Override
public List<Tree.Kind> nodesToVisit() {
return ImmutableList.of(Tree.Kind.CLASS);
}
#Override
public void visitNode(Tree tree) {
ClassTree classTree = (ClassTree) tree;
String className = classTree.simpleName().name();
if (className.endsWith("Service")) {
if(classTree.superClass() == null) {
return false;
}
if (!SUPER_CLASS.equals(localClassTree.superClass().symbolType().fullyQualifiedName())) {
reportIssue(tree, String.format("The class should extend SuperService or a class of type SuperService"));
}
}
}
}
}
How can I get the information related to superclass of the superclass?
You can simply call
Class superClassOfSuperClass = this.class().getSuperClass();
superClassOfSuperClass.method().invoke(this);
I'm not sure with your above example as there is a few typo's or misunderstanding with inheritance
You can collect all super classes until java.lang.Object was reached like so:
#Override
public void visitNode(Tree pTree) {
final ClassTree classTree = (ClassTree) pTree;
final Set<String> superclasses = new HashSet<>();
Type currentSuperclass = classTree.symbol().superClass();
while (currentSuperclass != null) {
superclasses.add(currentSuperclass.fullyQualifiedName());
currentSuperclass = currentSuperclass.symbol().superClass();
}
// ... do something with superClasses
super.visitNode(pTree);
}
#Override
public List<Kind> nodesToVisit() {
return ImmutableList.of(Tree.Kind.CLASS);
}
(Tested with sonar-java-plugin 6.3.0 and sonar-plugin-api 8.2.0)
Suppose I need some DerivedBuilder to extend some BaseBuilder. Base builder has some method like foo (which returns BaseBuilder). Derived builder has method bar. Method bar should be invoked after method foo. In order to do it I can override foo method in DerivedBuilder like this:
#Override
public DerivedBuilder foo() {
super.foo();
return this;
}
The problem is that BaseBuilder has a lot of methods like foo and I have to override each one of them. I don't want to do that so I tried to use generics:
public class BaseBuilder<T extends BaseBuilder> {
...
public T foo() {
...
return (T)this;
}
}
public class DerivedBuilder<T extends DerivedBuilder> extends BaseBuilder<T> {
public T bar() {
...
return (T)this;
}
}
But the problem is that I still can not write
new DerivedBuilder<DerivedBuilder>()
.foo()
.bar()
Even though T here is DerivedBuilder. What can I do in order to not to override a lot of functions?
Your problem is the definition of DerivedBuilder:
class DerivedBuilder<T extends DerivedBuilder>;
And then instantiating it with a type erased argument new DerivedBuilder<DerivedBuilder<...what?...>>().
You'll need a fully defined derived type, like this:
public class BaseBuilder<T extends BaseBuilder<T>> {
#SuppressWarnings("unchecked")
public T foo() {
return (T)this;
}
}
public class DerivedBuilder extends BaseBuilder<DerivedBuilder> {
public DerivedBuilder bar() {
return this;
}
}
Check ideone.com.
In addition to BeyelerStudios's answer, if you want to nest further, you can just use this:
class Base<T extends Base<?>> {
public T alpha() { return (T) this; }
public T bravo() { return (T) this; }
public T foxtrot() { return (T) this; }
}
class Derived<T extends Derived<?>> extends Base<T> {
public T charlie() { return (T) this; }
public T golf() { return (T) this; }
}
class FurtherDerived<T extends FurtherDerived<?>> extends Derived<T> {
public T delta() { return (T) this; }
public T hotel() { return (T) this; }
}
class MuchFurtherDerived<T extends MuchFurtherDerived<?>> extends FurtherDerived<T> {
public T echo() { return (T) this; }
}
public static void main(String[] args) {
new MuchFurtherDerived<MuchFurtherDerived<?>>()
.alpha().bravo().charlie().delta().echo().foxtrot().golf().hotel()
.bravo().golf().delta().delta().delta().hotel().alpha().echo()
.echo().alpha().hotel().foxtrot();
}
Instead of casting return (T) this; I here did a Class.cast(this).
To realize:
BaseBuilder.build(ExtendedBuilder.class).foo().bar().foo().bar();
Every class in the hierarch needs to know the actual final child class, hence I chose to make a factory method build in the base class.
The cast of this to the actual child is done in a final method of the base class too, providing return me();.
class BaseBuilder<B extends BaseBuilder<B>> {
protected Class<B> type;
public static <T extends BaseBuilder<T>> T build(Class<T> type) {
try {
T b = type.newInstance();
b.type = type;
return b;
} catch (InstantiationException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
protected final B me() {
return type.cast(this);
}
B foo() {
System.out.println("foo");
return me();
}
}
class ExtendedBuilder extends BaseBuilder<ExtendedBuilder> {
ExtendedBuilder bar() {
System.out.println("bar");
return me();
}
}
What I understand from your question is that the method foo() should be executed before method bar().
If that is correct, you can apply the Template Design Pattern.
Create a abstract method bar in the BaseBuilder.
And a new method say 'template'. The method template will define the sequence- first foo() is executed followed by bar().
DerivedBuilder will provide the implementation for the method bar.
public abstract class BaseBuilder {
public void foo(){
System.out.println("foo");
}
public abstract void bar();
public void template(){
foo();
bar();
}
}
public class DerivedBuilder extends BaseBuilder{
#Override
public void bar() {
System.out.println("bar");
}
public static void main(String[] args) {
BaseBuilder builder = new DerivedBuilder();
builder.template();
}
}
Hope this helps.
Suppose I have following class hierarchy:
class abstract Parent{}
class FirstChild extends Parent {}
class SecondChild extends Parent {}
And I'd like to create DTO objects from each child:
class abstract ParentDTO {}
class FirstChildDTO extends ParentDTO{}
class SecondChildDTO extends ParentDTO{}
I think I need a factory method something like this:
ParentDTO createFrom(Parent source);
Is there any nice way to do this in Java without instanceof checks and if/else statements?
EDIT:
This factory method does not work:
public ParentDTO create(Parent source)
{
return _create(source);
}
private FirstChildDTO _create(FirstChild source)
{
return new FirstDTO();
}
private SecondChildDTO _create(SecondChild source)
{
return new SecondDTO();
}
private ParentDTO _create(Parent source)
{
return new ParentDTO();
}
It only generates ParentDTOs and here is why:
Parent p = new FirstChild();
System.out.println(factory.create(p)); //ParentDTO
FirstChild f = new FirstChild();
System.out.println(factory.create(f)); //FirstChildDTO
If you insist on using a factory for DTO creation you can use simple method overloading. Example follows:
public class Factory {
public ParentDTO createDTO(Parent parent) {
return new ParentDTO();
}
public FirstChildDTO createDTO(FirstChild firstChild) {
return new FirstChildDTO();
}
public SecondChildDTO createDTO(SecondChild SecondChild) {
return new SecondChildDTO();
}
}
public class Parent {
}
public class FirstChild extends Parent {
}
public class SecondChild extends Parent {
}
public class ParentDTO {
#Override
public String toString() {
return this.getClass().getSimpleName();
}
}
public class FirstChildDTO extends ParentDTO {
#Override
public String toString() {
return this.getClass().getSimpleName();
}
}
public class SecondChildDTO extends ParentDTO {
#Override
public String toString() {
return this.getClass().getSimpleName();
}
}
public class App {
public static void main(String[] args) {
Factory factory = new Factory();
ParentDTO parentDTO = factory.createDTO(new Parent());
System.out.println(parentDTO);
FirstChildDTO firstChildDTO = factory.createDTO(new FirstChild());
System.out.println(firstChildDTO);
SecondChildDTO secondChildDTO = factory.createDTO(new SecondChild());
System.out.println(secondChildDTO);
}
}
Running the App as Java application in my IDE outputs:
ParentDTO
FirstChildDTO
SecondChildDTO
That's quite a complex question. I'd resolve this in few steps.
Parent class should have some kind of interface that would allow your factory to recognize, what data should your DTO object contain, like this (in PHP language):
class Parent
{
abstract function getDataFields();
}
class FirstChild extends Parent
{
function getDataFields()
{
return ['id' => $this->id, 'name' => $this->name, 'email' => $this->email];
}
}
class SecondChild extends Parent
{
function getDataFields()
{
return ['id' => $this->id, 'brand' => $this->brand, 'model' => $this->model];
}
}
Now, you only need a single factory, AND i would use a single class for DTO too, since you know what subclass of Parent
class DTOFactory
{
function createFromParent(Parent $parent)
{
return new DTO($parent);
}
}
class DTO
{
private $fields = [];
function __construct(Parent $parent)
{
foreach ($parent->getDataFields() as $field => $value) {
$this->fields[$field] = $value
}
}
function __get($field)
{
return $this->fields[$field];
}
}
Of course, there are a lot of ways to make DTO's in various languages, i can't cover this in detail, that's up to you.
You could do your factory method static, but if you want to avoid that, you have to use Dependency Injection of some sorts:
class MyController
{
private $dtoFactory;
function __construct(DTOFactory $factory)
{
$this->dtoFactory = $factory;
}
function returnDTOAction()
{
$object = new FirstChild(); // or some other way to get your child;
return $this->factory->createFromParent($object);
}
}
class DIContainer
{
private $instances = [];
function get($className)
{
if (!is_object($this->instances[$className]) {
$this->instances[$className] = new $className;
}
return $this->instances[$className] = new $className;
}
}
$container = new DIContainer;
$controller = new MyController($container->get('DTOFactory'));
This is a very simple example of DI Container, better examples have automatic dependency resolution, so you simply call them like $container->get('MyController'); and get a class with automatically resolved dependencies, but i won't go into further detail on this, since their implementation is heavily language-dependent, and i only stuck with a basic one.
Anyways, hope this helps. If you need some clarifications - feel free to comment.
You can code the factory method directly into the model class and utilize Java's covariant return type to return the correct type of DTO, for example:
public class Parent {
public ParentDTO createDTO() {
return new ParentDTO();
}
}
public class FirstChild extends Parent {
#Override
public FirstChildDTO createDTO() {
return new FirstChildDTO();
}
}
public class SecondChild extends Parent {
#Override
public SecondChildDTO createDTO() {
return new SecondChildDTO();
}
}
Problem
I'm trying to use Java generics to replace classes with similar methods. All of the examples that I've found cover simple examples, but I'm not sure if Java Generics are intended to be used this way.
I have 2 parent classes, and 2 child classes that have almost identical methods. Both parent classes derive from different classes as well. Ultimately, I want to be able to use one block of code to create and manipulate one of the parent classes, then its child class without a lot of switch statements or other flow control with duplicate code.
This is what I had in mind, even though I haven't beeen able to get it to work this way yet, whether it be syntax, or just not a feature of Generics.
Parent Classes
public class FooParent
{
private FooChild fooChild;
public FooChild getChild()
{
return fooChild;
}
}
public class BarParent
{
private BarChild barChild;
public BarChild getChild()
{
return barChild;
}
}
Child Classes
public class FooChild
{
public void print()
{
System.out.println("I'm a foo child");
}
}
public class BarChild
{
public void print()
{
System.out.println("I'm a bar child");
}
}
Generic Classes
public class GenericParent<T>
{
private T self;
public GenericParent(T self)
{
this.self = self;
}
public GenericChild getChild()
{
return new GenericChild(self.getChild());
}
}
public class GenericChild<T>
{
private T self;
public GenericChild(T self)
{
this.self = self;
}
public void print()
{
self.print();
}
}
How I want to use them
public static void main(String args[])
{
GenericParent parent;
// Only the initialization of the parent variable needs specialized code
switch(args[0])
{
case "foo":
parent = new GenericParent(new FooParent());
break;
case "bar":
parent = new GenericParent(new BarParent());
break;
}
// From here on out, it's all generic
parent.getChild().print();
}
Usage and desired output
java genericExample foo
> I'm a foo child
java genericExample bar
> I'm a bar child
Final Questions
Maybe "child" and "parent" are misnomers, because I know they're not actually inherited, but the bottom line is, the one class returns its "child" with certain methods. So this is a lot of code for a problem that may not actually be solvable this way, but hopefully you can answer me this:
Is this something that Java Generics can accomplish?
If not, is there a solution to this problem in Java?
Thanks!
Edit
My "Foo" and "Bar" classes are uneditable by me. My ultimate question is: can I store one instance of either class in a single variable without using a common parent class?
I think you want polymorphism, not generics:
public class test {
public class FooParent implements hasPrintableChildren
{
private FooChild fooChild;
public FooChild getChild()
{
return fooChild;
}
}
public class BarParent implements hasPrintableChildren
{
private BarChild barChild;
public BarChild getChild()
{
return barChild;
}
}
public class FooChild implements canPrint
{
public void print()
{
System.out.println("I'm a foo child");
}
}
public class BarChild implements canPrint
{
public void print()
{
System.out.println("I'm a bar child");
}
}
public interface hasPrintableChildren{
public canPrint getChild();
}
public interface canPrint{
public void print();
}
public static void main(String args[])
{
hasPrintableChildren parent;
// Only the initialization of the parent variable needs specialized code
switch(args[0])
{
case "foo":
parent = new FooParent();
break;
case "bar":
parent = new BarParent();
break;
}
// From here on out, it's all generic
parent.getChild().print();
}
}
OP clarified that he would be interested in the reflection option:
public static void main(String args[]) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException
{
Object parent;
// Only the initialization of the parent variable needs specialized code
switch(args[0])
{
case "foo":
parent = new FooParent();
break;
case "bar":
parent = new BarParent();
break;
}
// From here on out, it's all generic
Object child = parent.getClass().getMethod("getChild").invoke(parent);
child.getClass().getMethod("print").invoke(child);
}
Note: I would not recommend this sort of hard coded reflection. Code like this generally stinks of a bigger design problem.
Your parent seems a wrapper, a wrapper is a container, so yes it may be something that can benefit from a type parameter.
But I can't see any type parameter except in the constructor signature (and what is self? No bounds, no hints, no anything...), so using a generic type doesn't buy anything to you here. It's no use to introduce a type parameter if the methods you are interested in return void and declare an empty parameter list.
Here's the guidance: if methods in your classes would benefit from having a type parameter, ie if a type parameter is useful in any method return type or in the signature, then genericize your class. Otherwise, stick with what you currently have.
No. This is not usually something you would use Generics for, this is something you would use an Interface or an Abstract class for, and in your example, probably anonymous inner classes.
Here is an example that pretty much shows all that:
Main.java
public class Main {
public static void main(String args[])
{
AbstractParent parent;
// Only the initialization of the parent variable needs specialized code
switch(args[0])
{
case "foo":
parent = new FooParent();
break;
default:
parent = new BarParent();
break;
}
// From here on out, it's all generic
parent.getChild().print();
}
}
Child.java
public interface Child {
void print();
}
AbstractParent.java
public abstract class AbstractParent {
protected Child child;
public Child getChild() {
return child;
}
}
BarParent.java
public class BarParent extends AbstractParent {
public BarParent() {
child = new Child() {
#Override
public void print() {
System.out.println("I'm a bar child");
}
};
}
}
FooParent.java
public class FooParent extends AbstractParent {
public FooParent() {
child = new Child() {
#Override
public void print() {
System.out.println("I'm a foo child");
}
};
}
}
With some of the new language features in Java 8, you can do even cooler things. But let's leave that for another time.
Yes, generics together with polymorphism can help you:
public class Foo {} // declared elsewhere
public class Bar {} // declared elsewhere
public abstract class GenericParent<T> {
private T self;
public GenericParent(T self) {
this.self = self;
}
protected T getSelf() {
return self;
}
public abstract GenericChild<T> getChild();
}
public class FooChild extends GenericChild<Foo> {
public FooChild(Foo foo) {
super(foo);
}
}
public class BarChild extends GenericChild<Bar> {
public BarChild(Bar bar) {
super(bar);
}
}
public class FooParent extends GenericParent<Foo> {
public FooParent(Foo foo) {
super(foo);
}
public FooParent() {
this(new Foo());
}
#Override
public GenericChild<Foo> getChild() {
return new FooChild(getSelf());
}
}
public class BarParent extends GenericParent<Bar> {
public BarParent(Bar bar) {
super(bar);
}
public BarParent() {
this(new Bar());
}
#Override
public GenericChild<Bar> getChild() {
return new BarChild(getSelf());
}
}
You also have to change your main method slightly:
public static void main(String args[]) {
GenericParent<?> parent;
// Only the initialization of the parent variable needs specialized code
switch(args[0]) {
case "foo":
parent = new FooParent();
break;
case "bar":
parent = new BarParent();
break;
}
parent.getChild().print();
}
I have to handle two classes with identical methods but they don't implement the same interface, nor do they extend the same superclass. I'm not able / not allowed to change this classes and I don't construct instances of this classes I only get objects of this.
What is the best way to avoid lots of code duplication?
One of the class:
package faa;
public class SomethingA {
private String valueOne = null;
private String valueTwo = null;
public String getValueOne() { return valueOne; }
public void setValueOne(String valueOne) { this.valueOne = valueOne; }
public String getValueTwo() { return valueTwo; }
public void setValueTwo(String valueTwo) { this.valueTwo = valueTwo; }
}
And the other...
package foo;
public class SomethingB {
private String valueOne;
private String valueTwo;
public String getValueOne() { return valueOne; }
public void setValueOne(String valueOne) { this.valueOne = valueOne; }
public String getValueTwo() { return valueTwo; }
public void setValueTwo(String valueTwo) { this.valueTwo = valueTwo; }
}
(In reality these classes are larger)
My only idea is now to create a wrapper class in this was:
public class SomethingWrapper {
private SomethingA someA;
private SomethingB someB;
public SomethingWrapper(SomethingA someA) {
//null check..
this.someA = someA;
}
public SomethingWrapper(SomethingB someB) {
//null check..
this.someB = someB;
}
public String getValueOne() {
if (this.someA != null) {
return this.someA.getValueOne();
} else {
return this.someB.getValueOne();
}
}
public void setValueOne(String valueOne) {
if (this.someA != null) {
this.someA.setValueOne(valueOne);
} else {
this.someB.setValueOne(valueOne);
}
}
public String getValueTwo() {
if (this.someA != null) {
return this.someA.getValueTwo();
} else {
return this.someB.getValueTwo();
}
}
public void setValueTwo(String valueTwo) {
if (this.someA != null) {
this.someA.setValueTwo(valueTwo);
} else {
this.someB.setValueTwo(valueTwo);
}
}
}
But I'm not realy satisfied with this solution. Is there any better / more elegant way to solve this problem?
A better solution would be to create an interface to represent the unified interface to both classes, then to write two classes implementing the interface, one that wraps an A, and another that wraps a B:
public interface SomethingWrapper {
public String getValueOne();
public void setValueOne(String valueOne);
public String getValueTwo();
public void setValueTwo(String valueTwo);
};
public class SomethingAWrapper implements SomethingWrapper {
private SomethingA someA;
public SomethingWrapper(SomethingA someA) {
this.someA = someA;
}
public String getValueOne() {
return this.someA.getValueOne();
}
public void setValueOne(String valueOne) {
this.someA.setValueOne(valueOne);
}
public String getValueTwo() {
return this.someA.getValueTwo();
}
public void setValueTwo(String valueTwo) {
this.someA.setValueTwo(valueTwo);
}
};
and then another class just like it for SomethingBWrapper.
There, a duck-typed solution. This will accept any object with valueOne, valueTwo properties and is trivially extensible to further props.
public class Wrapper
{
private final Object wrapped;
private final Map<String, Method> methods = new HashMap<String, Method>();
public Wrapper(Object w) {
wrapped = w;
try {
final Class<?> c = w.getClass();
for (String propName : new String[] { "ValueOne", "ValueTwo" }) {
final String getter = "get" + propName, setter = "set" + propName;
methods.put(getter, c.getMethod(getter));
methods.put(setter, c.getMethod(setter, String.class));
}
} catch (Exception e) { throw new RuntimeException(e); }
}
public String getValueOne() {
try { return (String)methods.get("getValueOne").invoke(wrapped); }
catch (Exception e) { throw new RuntimeException(e); }
}
public void setValueOne(String v) {
try { methods.get("setValueOne").invoke(wrapped, v); }
catch (Exception e) { throw new RuntimeException(e); }
}
public String getValueTwo() {
try { return (String)methods.get("getValueTwo").invoke(wrapped); }
catch (Exception e) { throw new RuntimeException(e); }
}
public void setValueTwo(String v) {
try { methods.get("setValueTwo").invoke(wrapped, v); }
catch (Exception e) { throw new RuntimeException(e); }
}
}
You can use a dynamic proxy to create a "bridge" between an interface you define and the classes that conform but do not implement your interface.
It all starts with an interface:
interface Something {
public String getValueOne();
public void setValueOne(String valueOne);
public String getValueTwo();
public void setValueTwo(String valueTwo);
}
Now you need an InvocationHandler, that will just forward calls to the method that matches the interface method called:
class ForwardInvocationHandler implements InvocationHandler {
private final Object wrapped;
public ForwardInvocationHandler(Object wrapped) {
this.wrapped = wrapped;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Method match = wrapped.getClass().getMethod(method.getName(), method.getParameterTypes());
return match.invoke(wrapped, args);
}
}
Then you can create your proxy (put it in a factory for easier usage):
SomethingA a = new SomethingA();
a.setValueOne("Um");
Something s = (Something)Proxy.newProxyInstance(
Something.class.getClassLoader(),
new Class[] { Something.class },
new ForwardInvocationHandler(a));
System.out.println(s.getValueOne()); // prints: Um
Another option is simpler but requires you to subclass each class and implement the created interface, simply like this:
class SomethingAImpl extends SomethingA implements Something {}
class SomethingBImpl extends SomethingB implements Something {}
(Note: you also need to create any non-default constructors)
Now use the subclasses instead of the superclasses, and refer to them through the interface:
Something o = new SomethingAImpl(); // o can also refer to a SomethingBImpl
o.setValueOne("Uno");
System.out.println(o.getValueOne()); // prints: Uno
i think your original wrapper class is the most viable option...however it can be done using reflection, your real problem is that the application is a mess...and reflection is might not be the method you are looking for
i've another proposal, which might be help: create a wrapper class which has specific functions for every type of classes...it mostly copypaste, but it forces you to use the typed thing as a parameter
class X{
public int asd() {return 0;}
}
class Y{
public int asd() {return 1;}
}
class H{
public int asd(X a){
return a.asd();
}
public int asd(Y a){
return a.asd();
}
}
usage:
System.out.println("asd"+h.asd(x));
System.out.println("asd"+h.asd(y));
i would like to note that an interface can be implemented by the ancestor too, if you are creating these classes - but just can't modify it's source, then you can still overload them from outside:
public interface II{
public int asd();
}
class XI extends X implements II{
}
class YI extends Y implements II{
}
usage:
II a=new XI();
System.out.println("asd"+a.asd());
You probably can exploit a facade along with the reflection - In my opinion it streamlines the way you access the legacy and is scalable too !
class facade{
public static getSomething(Object AorB){
Class c = AorB.getClass();
Method m = c.getMethod("getValueOne");
m.invoke(AorB);
}
...
}
I wrote a class to encapsulate the logging framework API's. Unfortunately, it's too long to put in this box.
The program is part of the project at http://www.github.com/bradleyross/tutorials with the documentation at http://bradleyross.github.io/tutorials. The code for the class bradleyross.library.helpers.ExceptionHelper in the module tutorials-common is at https://github.com/BradleyRoss/tutorials/blob/master/tutorials-common/src/main/java/bradleyross/library/helpers/ExceptionHelper.java.
The idea is that I can have the additional code that I want to make the exception statements more useful and I won't have to repeat them for each logging framework. The wrapper isn't where you eliminate code duplication. The elimination of code duplication is in not having to write multiple versions of the code that calls the wrapper and the underlying classes. See https://bradleyaross.wordpress.com/2016/05/05/java-logging-frameworks/
The class bradleyross.helpers.GenericPrinter is another wrapper that enables you to write code that works with both the PrintStream, PrintWriter, and StringWriter classes and interfaces.