Given a few classes/interfaces.
public interface A {
public int doSomthing(int x);
}
public class B implements A {
int doSomthing(int x){
//actually do something
};
}
public class C extends B {
//does some specific implementations of what B does
// but does NOT override "int doSomething(int)"
}
How in a code using implementation C (or any subClass of C) may I determine (programatically) that B was the class implementing int doSomething(int).
Or if any of B's subclasses (lets say D which extends C) overrid "int doSomething(int)" how, when working with E (which extends D, yeah ... this is one large family of classes) may I define first parent that implemented "int doSomething(int)" ?
Thank you all in advance :)
You can do that using reflection, i.e. you start at the class the object has and check whether that class defines the method which is identified by the methodname and parameter types. If the class doesn't define that method you get its super class and check this, until you hit Object in which case the method isn't available at all.
For public methods, it's easier since Java has already a built-in method for this:
Class<?> mostSpecificImplementor =
yourObject.getClass().getMethod( "doSomthing", int.class ).getDeclaringClass();
Note that this only works for public methods, otherwise you'd have to search up the class hierarchy yourself (use getDeclaredMethod(...) in this case).
Related
Suppose I have an interface defined as:
public interface TestInterface1 {
public void add();
}
which is implemented by classes A, B and C.
Now I need to add a subtract functionality only to class C; for that I have created a new interface TestInterface2 and implemented that to class C:
public interface TestInterface2 {
public void sub();
}
Class C looks like this:
public class C implements TestInterface1, TestInterface2 {
public void add() {
System.out.println("I am in add");
}
public void sub() {
System.out.println("I am in Sub");
}
}
Now the problem is instances of C has been use in hundreds of places like this:
TestInterface1 c = new C();
And only class C is getting the add method of TestInterface1.
Is there any way or pattern to implement both the interfaces in class C so that where ever the object of class C is created, it gets both the method from TestInterface1 and TestInterface2?
If you can change your interfaces then make TestInterface1 extend the other one, so object created using first interface can use its parent methods.
public interface TestInterface1 extends TestInterface2{
public void add();
}
Before we get into this, you have to consider why you're even using interfaces for this at all. An interface guarantees that all instances are using the same implementations. If you want a specific class to have a more specific implementation, then that sounds more like a method on the concrete class more than it does a new interface at all.
Regardless, we can discuss your options. One of them is cleaner and conveys clear intent; the other muddies things.
The first option - which conveys clearer intent - is to eschew the usage of the more restrictive interface and instead use TestInterface2 for every declaration that you want to use C.
This means you'd write TestInterface2 c = new C(); everywhere you wanted to use it. Yes, you'd be changing it in all of the places that you're using C, but given that you have to have a method specifically attached to instances of C, this option is clearest.
This would be the same approach if you just wrote the method in C. There's really no difference between the two and I personally would prefer if you wrote the method that only belonged to C in C.
The second option - which muddies things and also requires Java 8 - is to use a default method. This requires that you implement it in the interface at first...
public interface TestInterface {
default void sub() {
System.out.println("I am in sub!");
}
}
...but you can override it in your class later. This muddies things because any class that implements TestInterface has access to this default method, which is likely not what you want for your requirements.
I understand why cyclic inheritance of classes is not allowed in Java but I did not understand why cyclic inheritance of interfaces is not allowed. To illustrate:
interface Foo extends Bar {/*methods and constants*/}
interface Bar extends Foo {/*methods and constants*/}
Interfaces do not need instantiation, then what prevents them from extending each other?
By the way, I read this question but this is not about interfaces but classes:
Cyclic inheritance hierarchy in Java
Thanks in advance.
No, but extension of an interface is a way of splitting up the agreement. Remember, an interface is an agreement to provide an implementation of a set of methods.
public interface A extends B {
public void myMethod();
public void myOtherMethod();
}
You're saying interface A is defined by these methods and all the methods in interface B. Now if interface B says..
public interface B extends A {}
you're saying that interface B is defined by the methods in interface A. Well what defines interface A. A couple of methods and interface B. And what defines interface B? Interface A, which is defined by a couple of methods and interface B! See where this is going?
It makes no logical sense to allow this.
Probably there are no theoretical difficulties, but this would create unnecessary complications. A few to name:
Currently traversal of class interfaces (via recursive calls of Class.getInterfaces()) is guaranteed to produce finite result, probably with repeats, but nevertheless. For example, such code is valid:
private static void fillInterfaces(Class<?> clazz, Set<Class<?>> set) {
if(clazz == null) return;
for (Class<?> iclass : clazz.getInterfaces()) {
set.add(iclass);
fillInterfaces(iclass, set);
}
fillInterfaces(clazz.getSuperclass(), set);
}
public static Set<Class<?>> getAllInterfaces(Class<?> clazz) {
Set<Class<?>> result = new HashSet<>();
fillInterfaces(clazz, result);
return result;
}
Similar code is already written and working in many places. With your proposal supplying the circular interface here would cause an infinite recursion.
Currently (in Java-8) interface can define a default implementation for its parent interface as well, replacing parent implementation if necessary. For example:
interface A {
default public String getX() {return "A";}
}
interface B extends A {
default public String getX() {return "B";}
}
static class C implements A, B {} // ok, C.getX() returns "B"
If now A extends B, then A wins:
interface A extends B {
default public String getX() {return "A";}
}
interface B {
default public String getX() {return "B";}
}
static class C implements A, B {} // ok, C.getX() returns "A"
But what if both A extends B and B extends A? Who will win? What new C().getX() will print? Or should it be new type of compilation error?
In general it seems that such feature would bring more problems than produce benefits.
See Java Language Specification 9.1.3 Superinterfaces and Subinterfaces :
An interface I depends on a reference type T if any of the following is true:
I directly depends on T.
I directly depends on a class C that depends on T (§8.1.5).
I directly depends on an interface J that depends on T (using this definition recursively).
It is a compile-time error if an interface depends on itself.
If circularly declared interfaces are detected at run time, as interfaces are loaded, then a ClassCircularityError is thrown (§12.2.1).
As for why, I like Andy Turner's comment:
If Foo extends Bar, then every instance of Foo is also a Bar. If Bar extends Foo, then every instance of Bar is also a Foo. If both were allowed to be true, then the only way the two conditions can be satisfied is if Foo == Bar.
I am asking this here because I really don't know how I should Google this. I need a confirmation of something that I probably figured out today. Some days ago I thought that if an object inherits a method of its father it means that it basically "has" the method in its code. But then I asked what if we do this:
class B extends A {
public B() {
}
public int getValue() {
return 2 * super.getValue();
}
}
class C extends B {
public C() {
}
public int getValue(int b) {
return 5 * b;
}
}
And lets say there is a class A that has the getValue() method too. Now an object of class C uses "its" getValue() method (without parameter) that it has inherited from B.
But super.getValue() still refers to class A, even though the method calling it was inherited.
Inheritance does not mean that class C "has" the method in its code, but that it can use it from B, right? super() still refers to the superclass of its "original" class.
Is that insight correct?
Inheritance does not mean that class C "has" the method in its code, but that it can use it from B, right?
Yes.
super() still refers to the superclass of its "original" class.
Yes. You are correct. super always refers to the Parent class of where it is being used. In this case it is being used in B and it's Parent is A. So referring to there.
A sub-class can override any non-private method of its super-class. If it doesn't override them, it inherits the implementation of these methods from its super-class.
Therefore you can say that the sub-class "has" access to all the non-private methods of all of its ancestors. And from a reference to an instance of a sub-class you can invoke any accessible (based on the access modifiers) method of the sub-class or any ancestor of the sub-class.
The super keyword allows you to invoke a method implementation of the super-class from the sub-class. This way you can override the implementation of a method of the super-class, but still execute the implementation of the super-class too.
In your class B :
This implementation overrides the getValue() of A :
public int getValue() {
return 5;
}
While this implementation overrides the getValue() of A, but still uses its logic :
public int getValue() {
return 2 * super.getValue();
}
Of course, you can't implement both in the same class, since they have the same signature.
I have 6 classes as shown in figure below.
Now, class A has an object of class B as a private variable defined. Also class A methods calls many methods from class B, for example B.method1().
Now, class A_Base1 is which is derived from class A, needs to call methods from the derived class B_Base1; for example B1.method2(). And also methods of class A_Base2 needs to call methods from class B_Base2; for example B2.method3().
Now in class A I define the variable as -
private B bObject
Now in method of A_Base1, I cannot cannot call the methods like bObject.method2() since its a base class object.
I need suggestions on -
Is it possible to call derived class object methods using base class object?
Or do I need to re-design this scenario in some other good way?
Using inheritance like this imo only makes sense if the Bx.methodX() do something that means she same to the different Ax. And in that case, you should name them that way:
public class B {
public void doWhatAMeans() {
method1();
}
public class B1 extends B {
#Override
public void doWhatAMeans() {
method2();
}
public class B2 extends B {
#Override
public void doWhatAMeans() {
method3();
}
and then you only need A to call doWhatAMeans() and the A1 and A2 only need to be injected the appopriate instances of Bx.
On the other hand, if doWhatAMeans does not make sense because the methodX do different things that mean different things to Ax, then you need to rethink your object model, probably the parallel structures A,A1,A2 and B,B1,B2 are wrong then.
you could always cast. suppose your class A provides this method:
protected B getBInstance() {
return bObject;
}
then in A_Base1 you could do something like:
((B_Base1)getBInstance()).method2();
this, however, is a VERY bad design. if your A_Base1 class needs an instance of B_Base1 it should be handed such an instance directly at construction time:
public class A_Base1 extends A {
private B_Base1 b1Object;
public A_Base1(B_Base1 instance) {
super(B_Base1); //works as a B for parent
this.b1Ovject = instance;
}
}
and then you can use that
since A is a parent of A_Base1 (I'm assuming extended) you can make the function call that Accesses B public (or protected) and then A_Base1 or A_Base2 can use the same function A does to call into B.
Something called the "bridge method" concept related to Java Generics made me stop at a point and think over it.
Btw, I only know that it occurs at the
bytecode level and is not available
for us to use.
But I am eager to know the concept behind the "bridge method" used by the Java compiler.
What exactly happens behind the scenes and why it is used?
Any help with an example would be greatly appreciated.
It's a method that allows a class extending a generic class or implementing a generic interface (with a concrete type parameter) to still be used as a raw type.
Imagine this:
public class MyComparator implements Comparator<Integer> {
public int compare(Integer a, Integer b) {
//
}
}
This can't be used in its raw form, passing two Objects to compare, because the types are compiled in to the compare method (contrary to what would happen were it a generic type parameter T, where the type would be erased). So instead, behind the scenes, the compiler adds a "bridge method", which looks something like this (were it Java source):
public class MyComparator implements Comparator<Integer> {
public int compare(Integer a, Integer b) {
//
}
//THIS is a "bridge method"
public int compare(Object a, Object b) {
return compare((Integer)a, (Integer)b);
}
}
The compiler protects access to the bridge method, enforcing that explicit calls directly to it result in a compile time error. Now the class can be used in its raw form as well:
Object a = 5;
Object b = 6;
Comparator rawComp = new MyComparator();
int comp = rawComp.compare(a, b);
Why else is it needed?
In addition to adding support for explicit use of raw types (which is mainly for backwards compatability) bridge methods are also required to support type erasure. With type erasure, a method like this:
public <T> T max(List<T> list, Comparator<T> comp) {
T biggestSoFar = list.get(0);
for ( T t : list ) {
if (comp.compare(t, biggestSoFar) > 0) {
biggestSoFar = t;
}
}
return biggestSoFar;
}
is actually compiled into bytecode compatible with this:
public Object max(List list, Comparator comp) {
Object biggestSoFar = list.get(0);
for ( Object t : list ) {
if (comp.compare(t, biggestSoFar) > 0) { //IMPORTANT
biggestSoFar = t;
}
}
return biggestSoFar;
}
If the bridge method didn't exist and you passed a List<Integer> and a MyComparator to this function, the call at the line tagged IMPORTANT would fail since MyComparator would have no method called compare that takes two Objects...only one that takes two Integers.
The FAQ below is a good read.
See Also:
The Generics FAQ - What is a bridge method?
Java bridge methods explained (thanks #Bozho)
If you want to understand why you need bridge method, you better understand what happens without it. Suppose there is no bridge method.
class A<T>{
private T value;
public void set(T newVal){
value=newVal
}
}
class B extends A<String>{
public void set(String newVal){
System.out.println(newVal);
super.set(newVal);
}
}
Notice that after erasure, method set in A became public void set(Object newVal) since there is no bound on Type parameter T. There is no method in class B the signature of which is the same as set in A. So there is no override. Hence, when something like this happened:
A a=new B();
a.set("Hello World!");
Polymorphism won't work here. Remember you need to override the method of parent class in child class so that you can use parent class var to trigger polymorphism.
What bridge method does is silently override the method in parent class with all the information from a method with the same name but a different signature. With the help of the bridge method, polymorphism worked. Though on the surface, you override the parent class method with a method of different signature.
It's insteresting to note that the compiler infers that MyComparator's method:
public int compare(Integer a, Integer b) {/* code */}
is trying to override Comparator<T>'s
public int compare(T a, T b);
from the declared type Comparator<Integer>. Otherwise, MyComparator's compare would be treated by the compiler as an additional (overloading), and not overridding, method. And as such, would have no bridge method created for it.
As indicated by this article and this article, the key reason of the Java bridge method is Type Erasure and Polymorphism.
Let's take the class ArrayDeque (source code) as example, it contains a clone() method as bellow, because the class ArrayDeque implements the Cloneable interface so it must override the Object.clone() method.
public class ArrayDeque<E> extends AbstractCollection<E>
implements Deque<E>, Cloneable, Serializable
{
public ArrayDeque<E> clone() {
....
}
}
But the problem is the return type of ArrayDeque.clone() is ArrayDeque<E>, and it did not match to the method signature defined in the parent Object.clone(), and in Object.java the return type is Object instead.
public class Object {
protected native Object clone() throws CloneNotSupportedException;
}
The return type mismatch is a problem for Polymorphism. So in the compiled result file ArrayDeque.class, the Java compiler generated two clone() methods, one match the signature in the source code, the other one match to the signature in the parent class Object.clone().
clone() method returns ArrayDeque<E>, which is generated based on the corresponding source code
clone() method returns Object, which is generated based on Object.clone(). This method is doing nothing but calling the other clone() method. And, this method is tagged as ACC_BRIDGE, which indicates this method is generated by the compiler for the Bridge purpose.