Java - Override a foreign method - java

I'm trying to make a spcial add-ons for my application. I need to override some methods of a class without editing the class file.
Here is a scheme:
class A
{
public void method1()
{
// Do something here
}
public int method2()
{
// Do something
}
}
Now from my class B, I want to override the method1 func from the class A, and force the A class to use my new method.
class B
{
public void method1()
{
Do something
}
}
I want to update my class A code without editing the A class. Is that possible?
Thanks.

use class B extends A and ovverride method that you want to change. how ever you have to use instance of class B not A. like
class B extends A
{
public void method1(){
Do something
}
}
A a = new B();
a.method1();

Sounds like proxy can solve your problem. Take a look at cglib
Enhancer e = new Enhancer();
e.setSuperclass(A.class);
e.setCallback(new MyCallback());
A proxied = e.create();
And here is sample impl of MyCallback class...
class MyCallback implements MethodInterceptor{
public Object intercept(Object obj,
Method method,
Object[] args,
MethodProxy proxy){
Object stuffToReturn = null;
if ("method1".equals(method.getName()) {
//Class B's method1 impl
} else {
//call the original method in class A
stuffToReturn = method.invoke(proxy, args);
}
return stuffToReturn;
}
}

Not if you create your objects using A constructor.
You could have B extend A, but you will have to instantiate objects as new B() (even if you can declare them as A, as in A obj = new B()).

No, in languages like Java this is not possible directly. new A will always create at runtime an instance of A, not of a derived B.
If it's possible (that is, if you control all the code which instantiates A), you can use some clumsy workarounds introducing a kind of indirection. For example, you can have a configurable factory producing As (which will on demand switch to producing Bs under the cover) -- this seems to be the Java way. (You'll need all the code construct As not directly, but through the factory.)
If I am not mistaken, the feature you are looking for is available in Objective C out of the box -- but not in Java.

By inheritance, yes. Simply change the class B definition : class B extends A

This has no sense. Overriding means precisely to re-define a method that is inherited from a super class. So here are some solutions :
B must extend A and then you can override one of the methods of A. Give it the same signature as in A, use the #Override annotation to be sure.
A has some dependency that is injected : method1 and method2 use some tierce object (C) to get the job done and the dependency is injected in A. Then B can use a A with custom C object that suits its needs. Most of code of A won't change that way.

One way to achieve this would be to use some sort of factory instance to create objects of type A instead of invoking the A() constructor directly in your code. Your add-on would then need to provide and register its own implementation of this factory which would create instances of class B. This only works if the add-on gets loaded and initialized before any instances of A were created.
Another approach would be to implement your own ClassLoader and use this to modify the bytecode of class A at loading time. You could search for tools for aspect oriented programming to implement this. This is only possible if you have control over the class loading process of class A.

No, you can't do that, it's impossible to modify the behavior of a class without actually modifying the class, however, there is a workaround:
B should be inherited from A. This is absolutely needed. A won't change, but its children classes might change in behavior
Overwrite method1() and method2()
Suppose you have an a object of the A class. If you convert it to B, its behavior will be your new, custom behavior.

Related

Refactoring and avoiding code duplication

I've ran into a problem that is new for me. Basically, someone else has already written a class A. The important parts looks like this
class A{
// some instance variables
public A(){
// Calls methods
build();
// Calls more methods
}
private build(){
item = makeItem();
anotherItem = makeAnotherItem();
// more code
}
private makeItem(){
// Does some things and calls updateItem()
}
private updateItem(){
// Does some things with instance variables of class A
// and calls yet another method in class A.
}
My problem is that build() does exactly what I need, but I need it in another class. Now here are the problems:
class A does a whole lot more than the things I've written, and so I cannot create an object of it. It would be pointless.
I've tried copying the build() method for my class B. However, build() uses other methods. And so I have to copy them as well and of course they call other methods and use instance variables declared in some other methods. Basically, I would have to copy 200 rows of code.
I'm guessing this problem actually has a name but I do not know what it's called and have therefore searched some basic terms only. What can I do to use build() in my class B?
You use the code of the build method in two classes but inheritance is not useful? Then you can reuse the code of the build method with composition. (hint Favor Composition over Inheritance) Create a new class C, which contains the build method. The class C is used by the classes A and B via composition. They delegate to the build method of the class C.
See the refactoring method of Martin Fowler.
https://sourcemaking.com/refactoring/smells/duplicate-code
also see
https://sourcemaking.com/refactoring/replace-inheritance-with-delegation
Always refactor in small steps. e.g. Put stuff together that belongs together, perhaps there is a neccessity for another class C which contains makeItem, makeAnotherItem and the corresponding instance variables. There is no general answer and it depends on how your code exactly looks like
first of all if build() in class A is using other private methods of A, that smells like you will need class A itself.
One option could be to create abstract class containing the common methods (including the build method), and extend this abstract class by class A and B. that way you will not have duplicate code
If for some reason you don't want to touch class A, I suggest you create an interface like :
public interface Builder{
void build()
}
and then implement this interface by your class B, and also extend class A so that you have implementation of the build method.
public class B extends A implements Builder{
// build() of class A will be used
// do other staff
}
In doing so, there is no change to class A at all (this might be desired if it is legacy code or something) + Builder can be used as a type in API you want to expose.

Changing object type in runtime using reflection

Is it possible to change the object type in runtime using reflection?
Let's say I have an instance of an object A. Objects of type B extend A. Would it be possible to change the object type of the instance of A into B so I can safely make a cast of A into B?
Maybe by changing the final attribute .class or a similar trick?
No, it is not possible.
Reflection that you mentioned allows discovering given class at runtime (i.e. finding method, field etc by name) and accessing methods and fields of objects at runtime without compiling the client code against specific class. For example you can invoke method foo() of any class.
Changing type of object actually does not make sense for me at all. Object contains is an instance of speicific class that have both data and methods. I can somehow imagine way to change the memory allocated for object at runtime using sun.misc.Unsafe, however I even cannot imagine how can you change the implementation of methods done in specific class associated with the object.
And the question that still remains here: why? Could you probably explain your task and ask for solution proposal?
EDIT
Following the new information posted by OP as a comment to my answer I'd like to add the following.
As far as I understand the situation is the following.
There is a third party library that implements class A and AFactory. OP uses code like the following:
A a = AFactory.create();
However he does not need A. He needs B extends A that implements additional functionality.
Possible solution is the following.
Create class B extends A:
public class B extends A {
private final A a;
public B(A a) {this.a = a;}
// delegate all methods of A, i.e.:
#Override
public boolean isA() {return a.isA()}
// add your functionality, e.g.
public boolean isC() {/* your code here*/}
}
Now use this class as following:
A a = AFactory.create();
B b = new B(a);
Now your can use all functionality of A via B and the additional functionality as well.

java - connecting interface to class member

Say I have an interface A and a class B that implements it.
Now, I also have some class C which extends class D (which means that it can't also extends B) but I also need there the functionality of interface A.
The solution I know is to have a member of A instantiated by B in C (which will implement A) and when implementing the functions of A call the matching function from the member of A.
Is there any way to create some connection between the functions of A and the member inside C? (so that java will know that every time it needs to call a function from A it will directly go and and run the matching function from the A member without me needing to write the code for it for every function of A)
A big thank you is waiting to each one of the helpers...
No. As already stated delegation must be implemented manually.
Having said that, you have a few options to simplify this: If you're working with Eclipse, select Source|Generate Delegate Methods... and select your member variable. Eclipse will then generate all the delegate methods for you. I don't know about other IDEs, but I would be surprised, if NetBeans et al. would not have a similar feature.
Another option, if you actually want to decorate existing collection classes, consider Google Guava's Google Guava's Collection Helpers.
Last, but not least, you could consider restructing your code and decorate your classes using Advices. Advices stem from Aspect Oriented Programming (AOP) and typically use a proxying mechanism to enrich original target classes. This is a rather advanced technique, but if you are determined to go down this road, have a look at Spring's AOP support.
So to sum up, here is your class hierarchies:
package common;
public interface A
{
void doStuff();
}
package commom.impl;
public class B implements A
{
void doStuff() {}
}
package real.service;
public class D
{
void doSomeRealStuff() {}
}
package real.service;
public class C extends D
{
void doSomeRealStuffForGood() {}
}
Assuming that each class is declared in its own source file.
Just to recall from the OP, I assume you need B stuff in C and not really A stuff. Because A is nothing but a contract and you need then the real implemting class to be fetched inside your C class in order to call the declared methods on.
In such a case, you may need to use the Inversion of Responsability approach, so that you declare an instacne of type B inside your C clas then you layer each method from B with a one having the same signature and that do nothing but delegate the real call to the instance member:
package real.service;
import common.A;
import common.impl.B;
public class C extends D
{
private A delegate;
public C ()
{
delegate = new B();
}
void doStuff() {
delegate.doStuff(); // Call the real delegate method when doStuff is called on an isntance of C.
}
void doSomeRealStuffForGood() {}
}
Note that this is a legal OO concept, since you are following an HAS-a even though some could consider it a high coupling.
Otherwise if you are not tied to the B class, and you may drop the declare methods in there for some others, you can declare an inner class that implements the A interface the way you need.
Edit:
Java does not support multiple inheritance, though you have provided a common contract in your A interface, so if you need all those methods (behavior) to be availble in your C class, it would be better to implement it directely and override all the interface methods.

Java architecture issue for extending instances (need for a pattern recommendation)

A service from external API which I am not allowed to modify returns me
MyClass instance = ServiceUtil.getThing();
I would like to extend this returned class and Add/Override a method but leave intacts the others, say 150 methods.
private class MyWrapperClass extends MyClass(){
public MyWrapperClass(){super();}
#Override public String toString(){ return "Blocked toString"; }
}
Is there any way to force this "casting" from the returned MyClass instance to my newly particular subtype??
NOTE: Please, not suggest the approach of making a constructor, passing the original object and having to copy and implement the 150 methods to call the wrapped object
If MyClass is an interface look at java.lang.reflect.Proxy and java.lang.reflect.InvocationHandler.
You can implement a dynamic proxy that always does the same. It is, always pass control to your original implementation... except when method X is invoked.
Something like:
class MyHandler implements InvocationHandler {
Object invoke(Object proxy, Method method, Object[] args) {
if (method is the one you want to change) {
do whatever
else
return method.invoke(originalObject, args);
}
}
Note: you must create this proxy implementation anyway:
MyClass original = ServiceUtil.getThing();
MyClass proxy = (MyClass) Proxy.newProxyInstance(
MyClass.class.getClassLoader(), // classloader to use
new Class[] { MyClass.class }, // interfaces to implement
new MyHandler()); // who does the dirty work when methods are invoked
I hope I get you right: you have a
MyClass instance = ServiceUtil.getThing();
but want something like
MyWrapperClass instance = (MyWrapperClass) ServiceUtil.getThing();
(which obviously doesn't work, even though MyWrapperClass extends MyClass).
The solution is to create a new instance of MyWrapperClass based on the MyClass and, sorry to say that, using the constructor is a good approach (public MyWrapperClass(MyClass myClass)).
Please, not suggest the approach of making a constructor, passing the original object
and having to copy and implement the 150 methods to call the wrapped object
You mean to say that "decoration" is not an option you would like to look at right?
But decoration will be a problem to you if MyClass is an interface type where you have to define those 150 odd methods, delegating the 149 method calls onto the decorated and overriding that one method.
If MyClass is a class type, then you don't need to write those 149 methods, right? or Did I get you completely wrong?

Can a Parent call Child Class methods?

Referring here
A is a precompiled Java class (I also have the source file)
B is a Java class that I am authoring
B extends A.
How can logic be implemented such that A can call the methods that B has.
The following are the conditions:
I don't want to touch A(only as a
last option though that is if no
other solution exists).
I don't want to use reflection.
As stated, if needed I could modify A.
What could be the possible solution either way?
Class A should define the methods it's going to call (probably as abstract ones, and A should be an abstract class, per Paul Haahr's excellent guide); B can (in fact to be concrete MUST, if the method are abstract) override those methods. Now, calls to those methods from other methods in A, when happening in an instance of class B, go to B's overrides.
The overall design pattern is known as Template Method; the methods to be overridden are often called "hook methods", and the method performing the calls, the "organizing method".
Yes it seems that if you override the super/base-classes's functions, calls to those functions in the base class will go to the child/derived class. Seems like a bad design in my opinion, but there you go.
class Base
{
public void foo()
{
doStuff();
}
public void doStuff()
{
print("base");
}
}
class Derived extends Base
{
#Override
public void doStuff()
{
print("derived");
}
}
new Derived().foo(); // Prints "derived".
Obviously all of Derived's methods have to be already defined in Base, but to do it otherwise (without introspection) would be logically impossible.
I would be rather hesitant to do this. Please correct me if I am wrong and then I will delete, but it sounds like you want to maintain an A object along with a B object. If they indeed are not the same object, the "tying together" (that's a scientific term) you'll have to do would be pretty ugly.

Categories

Resources