I wanted to optimize the code to use "BDTO extends ADTO", instead of duplicating method any() in DForm and EForm create a new class abstract (CForm) and where to put logic methods any ().
How resolve duplicate method? How is best Practice?
public class ADTO {
public String a;
public String getA() {return a;}
public void setA(String a) {this.a = a;}
}
public class BDTO extends ADTO{
public String b;
public String getB() {return b;}
public void setB(String b) {this.b = b;}
}
public abstract class CForm {
ADTO aDTO;
// BDTO bDTO;
public ADTO getADTO() {return aDTO;}
public void setADTO(ADTO aDTO){this.aDTO = aDTO;}
// public BDTO getbDTO() {return bDTO;}
// public void setbDTO(BDTO bDTO) {this.bDTO = bDTO;}
public void any() {//
aDTO.getA(); //
} //
// how resolve duplicate method ?
//public void any(){ // when i use only attribute aDTO and run any1() in EForm, aDTO is null
// bDTO.getA(); //
//}
}
public class DForm extends CForm {
public void anyD(){
getADTO().setA("test");
any(); // run method here is ok
}
}
public class EForm extends CForm{
//form using here any() and BDTO
public void anyE(){
getADTO().setA("test");
any(); //run method here aDTO is null, why?
}
}
Java doesn't allow duplicate methods (at least not like you would like).
What you could do however (and I think that is what you intended): You can make a single any() method that either randomly calls aDTO.getA() or bDTO.getB() or pick whichever is available and runs that one.
Your any() method could look like this (random):
public void any() {
if(new Random().nextBoolean())
aDTO.getA();
else
bDTO.getB();
}
Or like this (first available):
public void any() {
if(aDTO != null)
aDTO.getA();
else if(bDTO != null)
bDTO.getB()
}
Related
I have some generated code (i.e. it cannot be changed) that looks something like this.
class Generated1 {
public String getA() {
return "1";
}
public void setB(String b) {
}
public void setC(String c) {
}
public void setD(String d) {
}
}
class Generated2 {
public String getA() {
return "2";
}
public void setB(String b) {
}
public void setC(String c) {
}
public void setD(String d) {
}
}
I am exploring these objects by reflection. None of them implement any common interface but there's many of them and I want to treat them as if they implement:
interface CommonInterface {
String getA();
void setB(String b);
void setC(String c);
void setD(String d);
}
It certainly should be possible. This is considered perfectly good code
class CommonInterface1 extends Generated1 implements CommonInterface {
// These are perfectly good classes.
}
class CommonInterface2 extends Generated2 implements CommonInterface {
// These are perfectly good classes.
}
I suppose what I'm looking for is something like:
private void doCommon(CommonInterface c) {
String a = c.getA();
c.setB(a);
c.setC(a);
c.setD(a);
}
private void test() {
// Simulate getting by reflection.
List<Object> objects = Arrays.asList(new Generated1(), new Generated2());
for (Object object : objects) {
// What is the simplest way to call `doCommon` with object here?
doCommon(object);
}
}
My question: How do I treat an object that doesn't implement an interface but actually has all the code to do so as if it does implement the interface.
I want to replace
private void doCommon(Generated1 c) {
String a = c.getA();
c.setB(a);
c.setC(a);
c.setD(a);
}
private void doCommon(Generated2 c) {
String a = c.getA();
c.setB(a);
c.setC(a);
c.setD(a);
}
...
with
private void doCommon(CommonInterface c) {
String a = c.getA();
c.setB(a);
c.setC(a);
c.setD(a);
}
I know I can use a Proxy like this but I'd really prefer to use something better.
private void test() {
// Simulate getting by reflection.
List<Object> objects = Arrays.asList(new Generated1(), new Generated2());
for (Object object : objects) {
// What is the simplest way to call `doCommon` with object here?
doCommon(adapt(object));
}
}
private CommonInterface adapt(Object o) {
return adapt(o, CommonInterface.class);
}
public static <T> T adapt(final Object adaptee,
final Class<T>... interfaceToImplement) {
return (T) Proxy.newProxyInstance(
adaptee.getClass().getClassLoader(),
interfaceToImplement,
// Call the equivalent method from the adaptee.
(proxy, method, args) -> adaptee.getClass()
.getMethod(method.getName(), method.getParameterTypes())
.invoke(adaptee, args));
}
If you're using reflection, you don't need the two CommonInterfaceX classes, you can use a proxy implementing CommonInterface:
public class Wrapper implements InvocationHandler {
private final Object delegate;
public static <T> T wrap(Object obj, Class<T> intf) {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Object proxy = Proxy.newProxyInstance(cl, new Class<?>[] {intf},
new Wrapper(obj));
return intf.cast(proxy);
}
private Wrapper(Object delegate) {
this.delegate = delegate;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Method dmethod = delegate.getClass().getMethod(
method.getName(), method.getParameterTypes());
return dmethod.invoke(delegate, args);
}
}
You can use this class as follows:
List<Object> objects = Arrays.asList(new Generated1(), new Generated2());
for (Object object : objects) {
CommonInterface proxy = Wrapper.wrap(object, CommonInterface.class);
doCommon(proxy);
}
UPDATE: note that the same Wrapper class works with any interface.
There's no way to achieve a static type relationship between Generated1 and Generated2.
Even if you created CommonInterface1 and CommonInterface2, you still wouldn't be able to statically use a Generated1 object as a CommonInterface1 because new Generated1() is not a CommonInterface1 (and will never become one)
By far the simplest solution is to change your code generation to add the CommonInterface to Generated1 and Generated2.
If that's absolutely impossible, the only other way to avoid this code duplication is to go for reflection.
You can do it manuallly by reflection.
public class Generated {
public String getA() {
return "A";
}
public String sayHello(String name) {
return "hello " + name;
}
}
public class Helper {
private static final String METHOD_NAME = "getA";
private static final String METHOD_WITH_PARAM_NAME = "sayHello";
public static void main(String[] args) throws Exception {
Generated generated = new Generated();
accessMethod(generated);
accessMethodWithParameter(generated);
}
private static void accessMethod(Generated g) throws Exception {
Method[] methods = g.getClass().getDeclaredMethods();
for(Method method : methods) {
if(isCommonMethod(method)) {
String result = (String) method.invoke(g);
System.out.println(METHOD_NAME + "() = " + result);
}
}
}
private static boolean isCommonMethod(Method m) {
return m.getName().equals(METHOD_NAME) && m.getReturnType().equals(String.class);
}
private static void accessMethodWithParameter(Generated g) throws Exception {
Method[] methods = g.getClass().getDeclaredMethods();
for(Method method : methods) {
if(isCommonMethodWithParameter(method)) {
String result = (String) method.invoke(g, "Max");
System.out.println(METHOD_WITH_PARAM_NAME + "(\"Max\") = " + result);
}
}
}
private static boolean isCommonMethodWithParameter(Method m) {
return m.getName().equals(METHOD_WITH_PARAM_NAME) &&
m.getReturnType().equals(String.class) &&
m.getParameterTypes().length == 1 &&
m.getParameterTypes()[0].equals(String.class);
}
}
Output is
getA() = A
sayHello("Max") = hello Max
If you want to replace as your comment. I think you can do it easily
First, you create interface CommonInterface
interface CommonInterface {
String getA();
void setB(String b);
void setC(String c);
void setD(String d);
}
After that, you create 2 class Generated1 and Generated2 inherited CommonInterface
class Generated1 implements CommonInterface {
#overide
public String getA() {
return "1";
}
#overide
public void setB(String b) {
}
#overide
public void setC(String c) {
}
#overide
public void setD(String d) {
}
}
class Generated2 implements CommonInterface {
#overide
public String getA() {
return "2";
}
#overide
public void setB(String b) {
}
#overide
public void setC(String c) {
}
#overide
public void setD(String d) {
}
}
Structure
-ClassA
|---|
|---ClassAImplA
|---ClassAImplB
-Main
Class A:
public interface ClassA {
public void execute();
}
Implementaion A:
public class ClassAImplA implements ClassA
{
private int a = 5;
public ClassAImplA (int a){setA(a);}
#Override
public void execute() {
System.out.println(a);
}
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
Implementaion B:
public class ClassAImplB implements ClassA
{
private boolean b = false;
public ClassAImplB (int a){setB(b);}
#Override
public void execute() {
System.out.println(b);
}
public booelan getB() {
return b;
}
public void setA(boolean b) {
this.b = b;
}
main:
public class main {
/**
* #param args
*/
public static void main(String[] args) {
ClassAImplA param1 = new ClassAImplA(10);
ClassA = param1;
}
}
By doing this I make ClassA interchangeable,
but I lose the capability to access the parameter int a.
Is there a way to still make it interchangeable, and still have access to int a,
or in case of ClassAImplB, the field boolean b ?
There is a way, but it's not a good idea to do, as it defeats the purpose:
ClassAImplA param1 = new ClassAImplA(10);
ClassA = param1;
if (param1 instanceof ClassAImplA) {
param1x = (ClassAImplA) param1;
System.out.println(param1x.getA());
}
But don't do this. It defeats the purpose of the pattern.
The purpose of the pattern is to use objects of type ClassA,
without having to know how they work.
The getA method is only defined in ClassAImplA,
it's an implementation detail that should not be relevant to users of the ClassA type.
They shouldn't have to know. It's hidden.
This is called good encapsulation and information hiding.
you need one more class using composition to decide which implementation is needed.
public ClassHelper{
private A a;
public ClassHelper(A a){
this.a = a;
}
public void execute() {
this.a.execute();
}
}
public class main {
/**
* #param args
*/
public static void main(String[] args) {
ClassHelper param1 = new ClassHelper(new ClassAImplA(10));
param1.execute();
//or when you need classBIMpl
param1 = new ClassHelper(new ClassAImplB(true));
param1.execute();
}
}
And about the ability to access member of implA or implB , no you cannot have that flexibilty with this patter, whole point of this pattern is that caller need not be aware of implementation details.
Define an interface for the strategy and a Factory with different overloaded methods to create the concrete instances of the classes. Of course the methods are typed to the interface instead of the concrete classes.
The interface.
public interface Strategy {
void execute();
}
The first implementation.
public class ConcreteStrategy implements Strategy {
private boolean a;
public ConcreteStrategy(final boolean a) { this.a = a; }
public void execute() {}
}
The second implementation.
public class AnotherConcreteStrategy implements Strategy {
private int a;
public AnotherConcreteStrategy(final int a) { this.a = a; }
public void execute() {}
}
The factory.
public class Factory {
public static Strategy create(final boolean a) {
return new ConcreteStrategy(a);
}
public static Strategy create(final int a) {
return new AnotherConcreteStrategy(a);
}
}
if I have this interface
public interface someInterface {
// method 1
public String getValue(String arg1);
// method 2
public String getValue(String arg1, String arg2);
}
I want to be able to pass in 1 or 2 string to the getValue method without having to override both in each implementing class.
public class SomeClass1 impelments someInterface
{
#Override
public String getValue(String arg1);
}
public class SomeClass2 implements someInterface
{
#Override
public String getValue(String arg1, String arg2);
}
this won't work because SomeClass1 needs to implement method 2 and SomeClass2 needs to implement method 1.
Am I stuck doing this?
public interface someInterface2 {
public String getValue(String... args);
}
public class SomeClass3 implements someInterface2
{
#Override
public String getValue(String... args) {
if (args.length != 1) {
throw IllegalArgumentException();
}
// code
}
}
public class SomeClass4 implements someInterface2
{
#Override
public String getValue(String... args) {
if (args.length != 2) {
throw IllegalArgumentException();
}
// code
}
}
someInterface2 someClass3 = new SomeClass3();
someInterface2 someClass4 = new SomeClass4();
String test1 = someClass3.getValue("String 1");
String test2 = someClass4.getValue("String 1, "String 2");
Is there a better way of doing this?
An interface serves as a contract for the users of that interface: you specify what methods are available (in all implementations) and how they are called. If two implementations of an interface need a different method, then that method should not be part of the interface:
public interface Lookup {
}
public class MapLookup implements Lookup {
public String getValue(String key) {
//...
}
}
public class GuavaLookup implements Lookup {
public String getValue(String row, String column) {
// ...
}
}
In your program, you will know which implementation you use, so you can simply call the right function:
public class Program {
private Lookup lookup = new MapLookup();
public void printLookup(String key) {
// I hardcoded lookup to be of type MapLookup, so I can cast:
System.out.println(((MapLookup)lookup).getValue(key));
}
}
Alternative approach
If your class Program is more generic and uses dependency injections, you may not know which implementation you have. Then, I would make a new interface Key, which can be either type of key:
public interface Lookup {
// ...
public String getValue(Key key);
}
public interface Key {
}
public MapKey implements Key {
private String key;
// ...
}
public GuavaKey implements Key {
private String row, column;
// ...
}
The dependency injection in your program might come from some factory implementation. Since you cannot know which type of lookup you use, you need a single contract for getValue.
public interface Factory {
public Lookup getLookup();
public Key getKey();
}
public class Program {
private Lookup lookup;
public Program(Factory factory) {
lookup = factory.getLookup();
}
public void printLookup(Factory factory) {
System.out.println((lookup.getValue(factory.getKey()));
}
}
As of Java 8, you can have an interface provide an implementation of a method, through the use of the default keyword. Therefore a new solution would be to provide a default implementation of both methods which maybe throws an exception, then derive the actual implementation from the default interface.
Anyways here is how you can do this:
public interface SomeInterface {
// method 1
default String getValue(String arg1) {
// you decide what happens with this default implementation
}
// method 2
default String getValue(String arg1, String arg2) {
// you decide what happens with this default implementation
}
}
Finally, make the classes override the correct methods
public class SomeClass1 implements SomeInterface {
#Override
public String getValue(String arg1) {
return arg1;
}
}
public class SomeClass2 implements SomeInterface {
#Override
public String getValue(String arg1, String arg2) {
return arg1 + " " + arg2;
}
}
A solution (not very elegant) might look loke this:
public abstract class SomeClass {
public String getValue(String arg1) {
throw new IllegalArgumentException();
}
public String getValue(String arg1, String arg2) {
throw new IllegalArgumentException();
}
}
public class SomeClass1 extends SomeClass {
public String getValue(String arg1) {
// return sth
}
}
public class SomeClass2 extends SomeClass {
public String getValue(String arg1, String arg2) {
// return sth
}
}
However there's a drawback - SomeClass1 and SomeClass2 can't inherit directly other class.
If the second value can be considered optional in a sense and you always have the 2 arguments when calling you could create a wrapper class which implements the 2 parameter interface passing the 1 parameter implementation as a constructor parameter and calling that in the method, e.g. something like this:
interface A{
method1(P1)
}
interface B{
method2(P1, P2)
}
class Wrap implements B{
Wrap(A impl)
override method2(P1, P2){
call impl.method1(P1)
}
}
public interface SomeInterface {
default void print(String s) {
System.out.println(s);
}
}
public class SomeClass implements SomeInterface {
/**
* Note the this overloads {#link SomeInterface#print(String)},
* not overrides it!
*/
public void print(int i) {
System.out.println(i);
}
}
i have such java codes:
public class A {
public int get() {
// many codes
String s = new String();
//...
int n = 5;
return isEmpty(s) ? n : -1;
}
public boolean isEmpty(String s) {
return s.isEmpty();
}
}
now i want to just test get(), i don't want to test isEmpty() at the same, so i want to mock isEmpty(), just test a method, if it invokes another method of the class, can easymock mock the method?
A workable approach is to not mock A and do something like
public class TestableA extends A
{
#Override
public boolean isEmpty( String s )
{
// "mock" impl goes here, eg.:
return s;
}
}
and write your unit test in terms of TestableA instead. You can even create this in a #Before method:
public class UnitTest
{
private A a; // note: A, not TestableA!
#Before
public void setUp()
{
this.a = new A()
{
#Override
public boolean isEmpty( String s )
...
}
}
#Test
...
}
I would like to know how to create a contract with the caller for the Method parameter in the event the method has parameters itself. So that I use...
ClassA {
String string_ = "HI";
public static void subscribe(Object class, Method action) {
action.invoke(class, string_);
}
}
ClassB {
ClassB() {
ClassA.subscribe(this, this.getClass().getMethod("load", String.class));
}
public void load(String input) {
if(input.equals("HI")) {
...
}
}
}
I would like to know how to ensure the Method passed as "action" takes String as a parameter (i.e. ensure Method action == load(String){})? Is there something like this available:
public static void subscribe(Object class, Method action(String.class)) {
I want to do it in the method signature of subscribe so that it is obvious to the calling class (ClassB) that it needs to be prepared to take an argument of specified type.
EDIT: Updated last code bit so not to appear as if Method was generic. Poor choice of using <> on my part to represent an example of what I was trying to convey.
There's no way to do that in Java. The Method class is not generic, and there is no way for it to be so, because methods can take any number of parameters, and there is no way to make a class generic over a variable number of types.
Probably the best you can do is to declare your own type to use instead of Method:
public interface Action<T, P> {
public void invoke(T target, P parameter);
}
Then:
public static <T> void subscribe(T obj, Action<T, String> action) {
action.invoke(obj, string_);
}
ClassB() {
ClassA.subscribe(this, new Action<ClassB, String>() {
public void invoke(ClassB target, String parameter) {
target.load(parameter);
}
});
}
In C# there are means to achieve what you are trying to do but I can't think of a way to ensure that at compile time for java.
can you resort to using intefaces?
interface ILoader{
void load(String input);
}
ClassA {
String string_ = "HI";
public static void subscribe(ILoader loader) {
loader.load( string_);
}
}
ClassB implements ILoader {
ClassB() {
ClassA.subscribe(this);
}
public void load(String input) {
if(input.equals("HI")) {
...
}
}
}
Couldn't you use a slight modification of the Command Pattern?
puclic interface LoadCommand {
public load(String input);
}
public class ClassB implements LoadCommand {
public load(String input) {
// do stuff here
}
}
public class ClassA {
String myInput = "HI";
public static void subscribe(LoadCommand command) {
command.load(myInput)
}
}
The load method in the LoadCommand interface takes one String argument.