Reputation: 17
So, let's say I have a class called Users that has a private variable called name and a public getter method that just returns the name variable, how can I make so the getter returns name + " test" for all instances of the class instead without having access to the users class?
Upvotes: 1
Views: 362
Reputation: 1817
Well there are several ways to do this in Java…
First, you could extend your Users class and override the getter method like this:
public class TestUser extends User {
@Override
public String getName() { return super.getName() + "test"; }
}
Then you can reference TestUser instances by the User class and call on the getName method to use the new behavior:
User tu = new TestUser("username");
tu.getName(); // should return "usernametest"
Now... if by some reason cannot extend your class and cannot touch the existing User class, then another way to do this is by using a proxy via reflection:
If for example your User class implements an interface called IUser (or anything else) that declares a String getName()
method>
public interface IUser {
String getName();
}
Then using dynamic proxies you could create a IUser proxy that implements InvocationHandler that will intercept the getName method and alter it's return value.
public class DebugProxy implements java.lang.reflect.InvocationHandler {
private Object obj;
public static Object newInstance(Object obj) {
return java.lang.reflect.Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new DebugProxy(obj));
}
private DebugProxy(Object obj) {
this.obj = obj;
}
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
Object result;
try {
result = m.invoke(obj, args);
if ("getName".equals(m.getName())) {
return result + "test";
}
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
}
return result;
}
}
Then you can apply:
public class MainApp {
public static void main(String[] args) {
IUser userProxy = (IUser) DebugProxy.newInstance(new User("foo"));
System.out.println(userProxy.getName());
}
}
System.out.println will print "footest"
This is an ugly solution that will only work if your User class implements an interface that exposes the getName method. The only benefit is that you do not require inheritance nor alter the User class code:
I'd say inheritance is the way to go.
Hope this helps and welcome to stack overflow!
Upvotes: 4