I have one class and two interfaces
public class A implements B, C {
public static void main(String[] args) {
A a = new A();
a.foo();
}
}
public interface B {
default void foo(){
System.out.println("foo in B");
}
}
public interface C {
void foo();
}
The thing i'm concerned about is that java doesn't compile this giving an error that I must implement method from C. Hence I have a question. Why doesn't the default body cover that part, I mean the only thing java must be concerned about is that all the methods have their implementations, right? But for the class A, it's obvious that the implementation is given in B.
So why is java giving that error?
This is because interface B and C are not in same inheritance tree. And if they are not then Java compiler cannot be sure that implementing class has implementation of all methods of interface until it checks for each method from each implementing interface.
If you will define interface C as public interface C extends B then you will not get the error because in this case Java compiler will be sure that all methods are implemented.
Read more from JLS ยง9.4.1. Inheritance and Overriding
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.
If a class is implementing two interfaces, which inteface is actual the parent interface for that class in Java
interface A {
void m1();
}
interface B {
void m1();
}
public class C implements A,B {
public void m1() {
System.out.println("m1 method !!!");
}
public static void main(String[] args) {
C obj = new C();
obj.m1();
((A)obj).m1();
((B)obj).m1();
A objAsA = (A)obj;
objAsA.m1();
B objAsB = (B) obj ;
objAsB.m1();
}
}
There is no such concept as "the actual parent interface" in Java. All interfaces are on equal footing as the supertypes of the class. That doesn't change even in your case where both interfaces declare the same method signature: the same method in C implements both A and B.
BTW you don't need a cast operator to accomplish an upcast:
A objAsA = obj;
objAsA.m1();
B objAsB = obj;
objAsB.m1();
parent is a concept related for extension not implementation.
From Java Java Specification
interface Fish { int getNumberOfScales(); }
interface Piano { int getNumberOfScales(); }
class Tuna implements Fish, Piano {
// You can tune a piano, but can you tuna fish?
public int getNumberOfScales() { return 91; }
}
the method getNumberOfScales in class Tuna has a name, signature, and return type that matches the method declared in interface Fish and also matches the method declared in interface Piano; it is considered to implement both.
So its considered you implement BOTH
Your question doesn't make sense. You do not have 'parent' interfaces in java.
An interface is like a contract, you 'promise' to provide the methods listed in the interface. You are getting inheritance mixed up with interfaces.
Inheritance is where one class inherits parts of another class.
Like Dog -> Husky, Dog -> Poodle
An interface is where every Animal promises to have a method called public String getSpecies() for example.
In case you want to find all the interfaces a class has look at this question.
Determining the extended interfaces of a Class
While an interface can extend other interfaces, a 'normal' class doesn't have the concept of parent interfaces.
Thank you to akhil for spotting this.
You can think of child classes as specialisations of their parents, each level being more specific.
Animal -> Dog -> Husky. However every lower level has some common functionality with its siblings. All Dogs can bark(), all Animals can move().
Now try applying this logic to interfaces and you will see that it doesn't really make sense. An interface exists only to ensure that every class has a specific ability. All animals need to breathe, regardless of what species so you can make Animals implement Breathable. Which ensures that every animal has a method breathe().
Here class C implements both the interfaces and C is A and C is B as well.
An implemenation means you need to use that method in your class. So there is no parent of it. With extendions this can be, but then there can't be 2 parents to 1 class. For example:
public static void main(String[] args){
C c = new C();
c.m1();
}
class A {
public void m1() {
System.out.println("A printing");
}
}
class B {
public void m1() {
System.out.println("B printing");
}
}
class C extends A {
public void m1() {
System.out.println("C print");
}
}
printing: "C print"
C can't extend B at the same time. But it does override the method of class A. If C did not contain the method "m1()" then the method from class A was used and the console would print: "A printing"
I created interface TwoMethods. Source code:
interface TwoMethods<T>
{
public void method(T t);
}
Then I created class implementing this interface and after disassembling I saw 2 methods.
Class:
class A implements TwoMethods<A>
{
#Override
public void method(A a) {}
}
After disassembling:
class A implements TwoMethods<A> {
A();
public void method(A); //first
public void method(java.lang.Object); //second
}
Similarly for Comparable interface. Why when I create parametrized interface I have 2 methods. It is always, when I use parameter? I have additionally method with Object as argument?
method(java.lang.Object) is called the bridge method and it's generated because of type-erasure at compile time.
See Effects of Type Erasure and Bridge Methods
If we look at interface TwoMethods bytecode we will see that the actual method is
public abstract method(Ljava/lang/Object;)V
that is at bytecode level information about type parameter does not exist, type is erased, JVM simply does not know about generics, type parameters are replaced either with Object or in case if T extends X with X. So from the point of view of JVM
class A implements TwoMethods<A> {
public void method(A a) {
...
method(A a) does not override interface method because in bytecode it is in method(Object obj) can override it. To fix this problem compiler builds an implicit method, so called bridge method, in class A
public void method(Object obj) {
method((A)obj);
}
visible in bytecode only. Now for this code
A a = new A();
TwoMethods<A> tm = a;
tm.method(a);
compiler will replace tm.method(a) with call to the bridge
INVOKEINTERFACE test/TwoMethods.method(Ljava/lang/Object;)V
and this will redirect the call to A.method(A a);
I was reading through online for the reason as to why multiple inheritance is not allowed in Java and the following example was given to illustrate it:
class A {
public void doSomething() {
}
}
class B {
public void doSomething() {
}
}
class C extends A,B {
}
public static void main(String args) {
C c = new C();
c.doSoemthing(); // compiler doesnt know which doSeomthing to call.
The above example illustrates what we call a diamond problem where by both parent classes have the same method name. when a child class tries to retrieve it, the compiler gets confused.
My question is, how will an interface solve this kind of problem ?
It's not fair to say that multiple inheritance achieved through interfaces in java
Java support only multiple interface inheritance, and java does not support multiple inheritance.
You should see In mixin inheritance, one class is specifically designed to be used as one of the classes in a multiple inheritance scheme.
http://csis.pace.edu/~bergin/patterns/multipleinheritance.html
Lets think about the following code
interface P {
public void doSomething();
}
interface Q {
public void doSomething();
}
class A {
public void doSomething() {
}
}
class B {
public void doSomething() {
}
}
class C implements P,Q {
public void doSomething(){
// implementation
}
}
class D extends A,B { // suppose it is possible
}
now to use object of C you have the implementation of doSomething() in C class. Which is only implemented in C class.
But if you could create an object of D and call doSomething which method should be called? as this method is implemented in both A and B.
Diamond Problem
actually the real diamon problem is
class A {
public void doSomething() {
}
}
class B extends A{
public void doSomething() {
}
}
class C extends A{
public void doSomething() {
}
}
class D extends B,C { // suppose it is possible
// no implementation of doSomething.
}
it is called diamond because of it's diamond shape. Here if you want to do following
D d = new D();
d.doSomething(); // which method should be called now????
From wikipedia here is a nice real time example
For example, in the context of GUI software development, a class
Button may inherit from both classes Rectangle (for appearance) and
Clickable (for functionality/input handling), and classes Rectangle
and Clickable both inherit from the Object class. Now if the equals
method is called for a Button object and there is no such method in
the Button class but there is an overridden equals method in both
Rectangle and Clickable, which method should be eventually called?
The interface does not implement the doSomething() method, so you cannot call an interface method. Interface is a mere signature what methods to implement in the actuall (implementing) class. You would implement the doSomething() in your class C and that would be the method you are calling when invoking B.doSomething() or A.doSomething().
In the case of extending two claasses with two doSomething() methods, they could be having different implementations and you would not know which one is invoked. See this example:
class A {
public void doSomething() {
System.out.println("A");
}
}
class B {
public void doSomething() {
System.out.println("B");
}
}
class C extends A & B { //if this would be an option
}
public static void main(String args) {
C c = new C();
c.doSoemthing(); //Print "A" or "B" ???
}
Conclusion: It's an implementation thing. Interfaces do not offer any implementation for any method, so it's safe to inherit from interfaces having the same method signatures.
Multiple inheritance can inherit member data from many classes as well as all their functions. Multiple interfaces can only inherit function prototypes and they must be implemented by the child class.
An interface has no implementation of the method, and thus they both will be merged into the same method.
In fact, your object promises to implement a method called doSomething, but not tied to specifically one of the interfaces (serves both)
Answer lies in your question itself. In case of interface compiler does not get confused as there is no implementation in your interface. Its your concrete class which will provide the actual implementation .Hence no confusion.
Both classes provide code that the JVM can jump to when the call is made. This is where the ambiguity lies. Same problem with attributes, the compiler might have two attributes with the same name to look into, which will give a similar ambiguity.
An interface will not provide that code. Hence there will be no conflict.
Other languages that support multiple inheritance makes the compiler prohibit these ambiguities when they arise. And resolving them needs to be made ad hoc. I.e.
class C{
public void doSomething(){
// Call (this inferred)
B.doSomething();
// leave A.doSomething() alone.
}
}
I have an interface A, for which I have to supply a few different
implementations. However, those implementations share some helper methods, so
I moved those methods to an abstract base class.
Interface A {
void doX();
}
abstract Class B implements A {
protected void commonY() {
// ...
}
#Override
public abstract void doX();
}
Class C extends B {
#Override
public void doX() {
// ...
}
}
Class D extends B {
#Override
public void doX() {
// ...
}
}
My code works as expected, but I have a few questions:
Should I declare the abstract Method doX() in Class B? Why (not)?
Should I also explicitly declare "implements A" on Class C and D? Why (not)?
I think it would be better to do it as follows:
Interface A {
void doX();
}
abstract Class B {
protected void commonY() {
// ...
}
}
Class C extends B implements A{
public void doX() {
// ...
}
}
Class D extends B implements A{
public void doX() {
// ...
}
}
You shouldn't mix the interface (signature of methods) with the implementation.
Should I declare the abstract Method doX() in Class B? Why (not)?
No. It's an abstract class - defining the interface will mean that all subclasses will need to implement those methods. In other words, it's redundant.
Should I also explicitly declare "implements A" on Class C and D? Why (not)?
No, again - because your superclass (Abstract base class) implements that interface, your concrete subclasses will be guaranteed to implement that interface.
I'll just throw in the other option.
Turn abstract class B into an AUtil class that doesn't implement A. The method signatures may require an additional argument of type A to work with.
C and D implement A, and instantiate an AUtil internally. This does allow C and D to extend other classes.
I agree with JeeBee: consider implementing your helper methods somewhere other than an abstract base class.
If your helper method commonY() only exists in abstract base class B, all classes which implement Interface A will have to also extend base class B in order to take advantage of that implementation of commonY(). But, you might not always want to be forced to extend class B.
Also, what if you want to change the implementation of commonY() in the future? You will then affect lots of implementations of interface A. But if you don't control all these implementations of interface A, you may affect their functionality (in a bad way) without intending to.
Using an abstract base class in this situation may simply take away some flexibility without giving you anything in return.
An abstract class implementing an interface must implement that interface. Specifically, it must have a public method for every method-name-and-signature specified in that interface.
Inheritance is transitive. You do not need to write that class C implements interface A if class C derives class B which implements interface A. However, there isn't much harm to it either.
I would not declare doX() in B and not add "implements A" on C and D because you should not repeat yourself.
The abstract doX() in B adds nothing, as it's already specified by "implements A". The same is true for adding "implements A" to C and D.
The only possible use for those clauses would be documentation: If you want to make it very explicit that C (or D) is-a A, then you could add the implements, but you should be aware that it really doesn't matter to the compiler.