I have few classes that implements some interface. Now I want to create new class, which can extend one of them, based on runtime calculation while using interfaces methods. Let's talk in code:
public interface Interface {
public void doSomething();
}
public class A implements Interface {
#Override
public void doSomething() {
System.out.println("hello");
}
}
public class B implements Interface {
#Override
public void doSomething() {
System.out.println("hi");
}
}
These are existing classes, so now I need to do something like this (which is not working of course):
public class C<T extends Interface> extends T {
public void doSomethingElse() {
this.doSomething();
}
public static void main(String[] args) {
C c;
if(isSomethingLoaded) {
c = new C<A>();
} else {
c = new C<B>();
}
c.doSomethingElse();
}
}
Is it possible somehow, except the way that I pass argument Interface other to C's constructor and store to class property..?
A class cannot extend from its type parameter.
Use composition instead of inheritance:
public class C<T extends Interface> {
private final T foo;
public C(T foo){
this.foo = foo;
}
public void doSomethingElse() {
foo.doSomething();
}
public static void main(String[] args) {
C<?> c;
if(isSomethingLoaded) {
c = new C<>(new A());
} else {
c = new C<>(new B());
}
c.doSomethingElse();
}
}
You might even not need the type parameter here, but just use the interface type as argument/ member type.
I think it's situations like this which show why we have the rule of favouring composition over inheritance. Consider this solution using composition:
public class Test {
public interface Interface {
void doSomething();
}
public static class A implements Interface {
#Override
public void doSomething() {
System.out.println("Doing A");
}
}
public static class B implements Interface {
#Override
public void doSomething() {
System.out.println("Doing B");
}
}
public static class C implements Interface {
private Interface composedWith;
public C(Interface i) {
this.composedWith = i;
}
#Override
public void doSomething() {
this.composedWith.doSomething();
}
}
public static void main(String[] args) {
C c;
if(isSomethingLoaded) {
c = new C(new A());
} else {
c = new C(new B());
}
c.doSomething();
}
}
Personally, I feel this is a clearer and move flexible way of achieving what you are trying to do.
Related
As in the example below, I need to do an operation on an object of type A passing a reference to an object of type B to the function, but the expression is invalid:
a.setId(a.getId());
public class Example {
public static void main() {
A<?> a = new B();
useA(a);
B b = new B();
useA(b);
useB(b);
}
static void useA(A<? extends A.AId> a) {
a.setId(a.getId());
}
static void useB(B b) {
b.setId(b.getId());
}
}
interface A<ID extends A.AId> {
ID getId();
void setId(ID id);
interface AId {
}
}
class B implements A<B.BId> {
#Override
public BId getId() {
return null;
}
#Override
public void setId(BId id) {
}
static class BId implements A.AId {
}
}
What type should the a parameter of the useA function be for correct assignment?
Hello you can try it.
static <T extends A.AId> void useA(A<T> a) {
a.setId(a.getId());
}
interface Y {
void search(String name);
}
class A implements Y {
void search(String name) {
//Is it possible to say: "If I was called from class B then do a search("B");
}
}
class B extends A {
}
public class Main {
public static void main(String[] args) {
B b = new B();
b.search();
}
}
Given the above code is it possible to reason in superclass which subclass was used for calling a method?
The reason I want to do this is because the code in Search is very similar for all Subclasses, the only thing that changes is the Classname, so I thought there is no need to Override in each subclass. I have updated the code to reflect this. Please let me know if there is a better way of doing it/
Calling this.getClass() inside your search method will give you the concrete class of the current instance.
For example:
class Example
{
static class A {
public void search() {
System.out.println(getClass());
}
}
static class B extends A {}
public static void main (String[] args) throws java.lang.Exception
{
new A().search();
new B().search();
}
}
outputs
class Example$A
class Example$B
The cleanest way to do it is to override the method in each subclass.
interface Y {
void search();
}
class A implements Y {
public void search(){
search("A");
}
protected void search(String name) {
// implement your searching algoithm here
}
}
class B extends A {
public void search(){
search("B");
}
}
public class Main {
public static void main(String[] args) {
B b = new B();
b.search();
}
}
That's the way inheritance is suppose to works. A super class should not know its subclasses.
And, in case you extends your class B, you can easily either:
-Keep the same behaviour as B:
class C extends B {
// do nothing, when calling search, it calls the method implemented in B
}
-Change the behaviour to search for "C"
class C extends B {
public void search(){
search("C"); // or search("whateveryouwant")
}
}
You can simply override the method in class B.
The other way could be to write the search() method as
void search() {
if (this.getClass().equals(B.class)) {
//The logic for B
} else if (this.getClass().equals(A.class)) {
//The logic for A
}
}
You have to provide the fully qualified name for the class.
Better follow template pattern.
interface Y {
void search(String name);
}
abstract class AbstractionTemplate implements Y{
#Override
public void search(String name) {
//a lot of code.
System.out.println("common stuff start");
doImplspecificStuffOnly();
System.out.println("common stuff end");
//a lot of code.
}
abstract void doImplspecificStuffOnly();
}
class A extends AbstractionTemplate{
#Override
void doImplspecificStuffOnly() {
System.out.println("a's stuff");
}
}
class B extends A {
#Override
void doImplspecificStuffOnly() {
System.out.println("B's stuff");
}
}
public class Main {
public static void main(String[] args) {
B b = new B();
b.search("hey");
}
}
Having the following example:
public class Test {
public static class A {}
public static void main(String[] args) {
A a = new A();
m1(a);
}
public static <T> void m1(T t) {
// t.getClass().getSimpleName() is A
// t instanceof A is true
m2(t);
}
/* Not called */
public static void m2(A a) {
System.out.println("A");
}
public static void m2(Object o) {
// o.getClass().getSimpleName() is A
// o instanceof A is true
System.out.println("O");
}
}
I don't understand why m2(Object o) is chosen instead of m2(A a). As you can see, when m2(t) is called, t "is an A".
Output:
actual
O
expected
A
How can I use generics for the situation above so that m2(A a) is chosen?
Edit:
I'd like to have a general solution that will work even if I add a type B (similar to A).
...
public static void main(String[] args) {
A a = new A();
m1(a);
B b = new B();
m1(b);
}
...
public static void m2(B b) {
System.out.println("B");
}
...
Output:
actual
O
O
expected
A
B
You have to do:
public static <T extends A> void m1(T t) {
m2(t);
}
Otherwise the compiler cannot infer that the passed parameter is compliant with m2(A a) and with pick m2(Object o) instead.
You are looking for double dispatch which Java does not support. I do not think that generics can help here, but there's the visitor design pattern with which you can emulate it:
public class Test {
public static interface Visitable {
void accept(Visitor visitor);
}
public static class A implements Visitable {
#Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public static class B implements Visitable {
#Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public static interface Visitor {
void visit(A a);
void visit(B b);
}
public static class PrintingVisitor implements Visitor {
#Override
public void visit(A a) {
System.out.println("A");
}
#Override
public void visit(B b) {
System.out.println("B");
}
}
public static void main(String[] args) {
Visitable visitable = new A();
m(visitable);
visitable = new B();
m(visitable);
}
public static void m(Visitable visitable) {
visitable.accept(new PrintingVisitor());
}
}
I'm developing an application which builds on a class written by another developer (for which I do not have the source).
I wish to use all of the functionality of said class but also to extend it with additional functionality. Ordinarily to achieve this I would have defined an interface (MyInterface) and have extended the external class (TheirClass) from my own (MyClass) while implementing MyInterface.
public interface TheirClassInterface {
public void theirMethod1();
public void theirMethod2();
}
public class TheirClass implements TheirClassInterface {
public void theirMethod1() { ... }
public void theirMethod2() { ... }
}
public class TheirOtherClass {
public void theirOtherMethod1(TheirClassInterface o) { ... }
}
public interface MyInterface() {
public void myMethod1();
}
public class MyClass extends TheirClass implements MyInterface {
public void myMethod1() { ... }
}
public class MyNewClass extends MyClass {
public void MyNewClassMethod() { ... }
}
The problem is complicated by the fact that:
I now wish to create a new class (MyNewClass) which adds additional functionality to MyClass but I don't want my code to be dependent on TheirClass.
I wish to be able to use my class as a parameter to the method of TheirOtherClass.
To combat this I refactored my code to instead use composition over inheritance and implementing TheirClassInterface. This works but requires me to implement many methods and delegate them to theirClassObject (in reality TheirClassInterface contains a very large number of methods).
public interface TheirClassInterface {
public void theirMethod1();
public void theirMethod2();
}
public class TheirClass implements TheirClassInterface {
public void theirMethod1() { ... }
public void theirMethod2() { ... }
}
public class TheirOtherClass {
public void theirOtherMethod1(TheirClassInterface o) { ... }
}
public interface MyInterface() {
public void myMethod1();
}
public class MyClass implements TheirClassInterface, MyInterface {
private TheirClass theirClassObject;
public void myMethod1() { ... }
public void theirMethod1() { theirClassObject.theirMethod1(); }
public void theirMethod2() { theirClassObject.theirMethod2(); }
}
public class MyNewClass extends MyClass {
public void MyNewClassMethod() { ... }
}
My question is whether my approach is appropriate in this case and whether it could be improved upon as it seems to me that my code uses an excessive amount of delegation to get the job done.
Many thanks for any guidance anyone can give on this.
Danny
First, as java is a strongly-typed single inheritance language, you cannot escape the delegation.
But you can avoid having to write a lot of delegation CODE, by using a dirty little trick with Proxies and reflection.
Code follows
public interface Interface1 {
void m1();
}
public interface Interface2 {
void m2();
}
public class Class1 implements Interface1 {
public void m1() {
System.out.println(1);
}
}
public class Class2 implements Interface2 {
public void m2() {
System.out.println(2);
}
}
public interface MixinInterface extends Interface1, Interface2 {
}
And this is how the magic happens
package j.with.pseudo.multiple.inheritance;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MixinBuilder {
public static Object buildMixed(Class _interface, Object... impls){
InvocationHandler h = new MixinHandler(_interface.getInterfaces(), impls);
return Proxy.newProxyInstance(MixinBuilder.class.getClassLoader(),
new Class[]{_interface}, h);
}
public static void main(String[] args) {
Class1 o1 = new Class1();
Class2 o2 = new Class2();
MixinInterface almost_like_multiple_inheritance_guy =
(MixinInterface) buildMixed(MixinInterface.class, o1, o2);
almost_like_multiple_inheritance_guy.m1();
almost_like_multiple_inheritance_guy.m2();
}
private static class MixinHandler implements InvocationHandler{
private Class[] interfaces;
private Object[] impls;
public MixinHandler(Class[] interfaces, Object[] impls) {
this.interfaces = interfaces;
this.impls = impls;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
int i=0;
for(Class _interface : interfaces){
if(method.getDeclaringClass().isAssignableFrom(_interface)){
return method.invoke(impls[i], args);
}
i++;
}
// TODO Auto-generated method stub
throw new RuntimeException("Method not found: "+method);
}
}
}
Pretty cool huh? :-)
You can't not-depend on a class if you're extending it; it's like having a definition of Human, which does not depend on the definition of Mammal, your optinos are to rewrite everything in the parent, or depend on it.
Many thanks for the answers so far. I've come up with a solution which I think seems reasonable and allows me to fully encapsulate the foreign class.
At the moment I've returned to the method discussed in the first block of code (repeated and extended below) and am now implementing my MyInterface interface for MyNewClass and delegating all interface operations to a composed object. The object to delegate to is decided at runtime by calling a static method on a Factory.
public interface TheirClassInterface {
public void theirMethod1();
public void theirMethod2();
}
public class TheirClass implements TheirClassInterface {
public void theirMethod1() { ... }
public void theirMethod2() { ... }
}
public class TheirOtherClass {
public void theirOtherMethod1(TheirClassInterface o) { ... }
}
public interface MyInterface() {
public void myMethod1();
}
public class MyClass extends TheirClass implements MyInterface {
public void myMethod1() { ... }
}
public class MyNewClass implements MyInterface {
private MyInterface myObject;
public MyNewClass() {
myObject = MyClassFactory.createMyClass();
}
public void myMethod1() {
myObject.myMethod();
}
public void MyNewClassMethod() { ... }
}
Once again, thanks for the ideas. I'm now going to look into them all and see if I can use them to improve my code.
Cheers,
Danny
If you have a base class that is in a jar file that looks like:
public class A {
public void awesome(int i){
}
}
...which is extended by these classes (also in a jar) as follows:
public class A1 extends A {
#Override
public void awesome(int i){
}
}
and
public class A2 extends A {
#Override
public void awesome(int i){
}
}
...is it possible to override the base function in a generic way?
Say there is an implementation that was being added via anonymous inner class - can you code that such that the entire anonymous inner implementation only appears once?
So instead of:
public class Test {
public static void main(String args[]){
A1 mySpecialA1 = new A1(){
#Override
public void awesome(int i){
//awesome implementation
}
};
A2 mySpecialA2 = new A2(){
#Override
public void awesome(int i){
//awesome implementation
}
};
}
}
...you could have (this is where it breaks down):
public class SpecialAFactory {
public static <T extends A> getSpecialA(){
return new T(){
#Override
public void awesome(int i){
//only once
}
};
}
}
So ultimately you would be passing in the subclass that you want to get a new anonymous instance of.
Although you cannot do it with generics, there is a simple, easy to understand, solution that lets you avoid code duplication in cases like that:
public class Test {
public static void main(String args[]){
A1 mySpecialA1 = new A1(){
#Override
public void awesome(int i){
awesomeImplementation(i);
}
};
A2 mySpecialA2 = new A2(){
#Override
public void awesome(int i){
awesomeImplementation(i);
}
};
}
private static void awesomeImplementation(int i) {
//awesome implementation
}
}