Strange behavior observed in inheritence - java

I have an interface, IfcBase which is implemented by another class Base. This class is further extended by a second class SubBase. Further SubBase class implements another interface IfcNew. Both these interfaces have a method declared that has the same signature. Now SubBase does not define the method from IfcNew. I now create an instance of SubBase and assign it to the reference type IfcNew. I then invoke the lone method and get an output. The method from IfcBase was executed in this case. I believe this should not be allowed at some stage, either during compilation or execution. I fail to understand the behavior and solicit help. The source is below. Thanks a lot!
public interface IfcBase
{
public void printString();
}
public class Base implements IfcBase
{
public void printString()
{
System.out.println("Base Class");
}
}
public interface IfcNew
{
public void printString();
}
public class SubBase extends Base implements IfcNew
{
//
}
public class Test
{
public static void main(String[] args)
{
IfcNew i = new SubBase();
i.printString(); //Output:Base Class
}
}

This is how inheritance works in Java.
You have a method called public void printString() implemented in Base, from which you extend SubBase. As a result this implementation will be implicitly available in this class.
For the implements IfcNew part in the SubBase declaration, compiler will only check to see if SubBase has a method implemented which has the same signature as public void printString(). Since it implicitly inherits this implementation from Base, it has nothing to complain about.
This behavior can be easily understood if you look at it from OO design point of view. Please take a look at this article which I wrote few years ago. Look under the section called Method signature, Object Interface, Types, Subtypes and Supertypes. By the definition of subtype that is provided there, SubBase is already a subtype of IfcNew, so compiler has no problem with it.

This is the correct behavior of inheritance in Java.
There is no warning when implementing multiple interfaces with same-signature methods, because resolution takes place at runtime.
In this case, your SubBase class does not need to implement printString as its parent does, even if it isn't the "same" printString: the identical signature allows resolution at runtime.

This is obvious and not strange. This is because the method with same signature is already implemented in the base class and when you extend the base class it is automatically inherited. Now when you try to assign the object to IfcNew reference the method implemented is called which is not overriden in subclass, meaning that the base class method is called which actually is the implementation of IfcBase.

Related

Rules for Diamond prob resolution or Multiple Inheritance in Java8

In Java a class can extend only one parent class but can implement multiple interfaces.
With
the introduction of default methods in Java 8 interface, there’s the possibility of a class inheriting more than one
method with the same signature by implementing 2 interfaces having the same default method
This can create diamond problem as in C++
Example in below code the output of
new C().hello(); is
This is Second
public interface First {
default void hello(){
System.out.println("This is First");
}
}
public interface Second extends First {
default void hello(){
System.out.println("This is Second");
}
}
public class MyClass implements First,Second {
public static void main(String[] args) {
new MyClass().hello();
}
}
What are the resolution rules that Java uses to resolve Diamond Problem?
A simple answer like who takes precedence and when will be great.
Following are the rules to follow when a class inherits a method with the same signature from multiple places (another class or interface):
Classes always win. A method declaration in the class or a superclass
takes priority over any default method declaration.
Otherwise, sub-interfaces win: the method with the same signature in the most specific defaultproviding
interface is selected. (for example in your case method from Second interface should run as Second extends First).
Finally, if the choice is still ambiguous, the class inheriting from multiple interfaces has to
explicitly select which default method implementation to use by overriding it and calling the
desired method explicitly.
There is the Oracle Tutorial that explains this pretty much in detail.
You have basically overridden your method from First interface and the most specific interface method is chosen.
Your snippet is no diamond problem as interface second extends interface first and overrides the method hello.
Without extending interface second the compiler throws an error
Duplicate default methods named hello with the parameters () and () are inherited from the types Second and First
Implementing two Interfaces that declare the same default Method leads to an compilation error:
MyClass inherits unrelated defaults for sayHi() from types InterfaceA and InterfaceB
So there's no Diamond-Problem ;)
To solve this you can override the Method in the implementing Class and either implement it there or defer to the correct Interface.
In your case it would look like that (in case you want to use the method of Interface First):
public class MyClass implements First,Second {
public void hello() {
First.super.hello();
}
}

Why don't implement all method in interface Comparator?

Today, I'm trying to learn some features in Java 8, specific about Lambda Expressions. I create a new Comaparator like this :
Comparator<String> strCom = new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
return 0;
}
};
When I read code inside Comparator interface, I have got confused. Althrough interface Comparator have two method compare() and equals(), we don't need implement all of them. I had found some reason why we don't need implement method equals() here. But i also read in javadocs
If your class claims to implement an interface, all methods defined by that interface must appear in its source code before the class will successfully compile. What Is an Interface?
So, can someone help me understand this ? Do not override equals() is still legal ?
equal is not needed to implement because it is inherited from the Object class, as everything in Java is an Object
As you can see in the documentation the equal Method is already defined in the Object class:
https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html
You only need to implement the equals method if you want to check if two Comparators have the same data and therefore are "equal", but this is probably not what are you looking for, as Comparators normally do not hold any instance variables
The tutorial is trying to introduce the concept of interfaces through a simple example, but it ends up being misleading.
Take this code for example:
public interface MyInterface {
public void foo();
public void bar();
}
public class Super {
public void foo() { System.out.println("foo"); }
}
public class Sub extends Super implements MyInterface {
public void bar() { System.out.println("bar"); }
}
This is perfectly valid code, despite the fact that Sub only explicitly implements one of MyInterfaces methods. It's easy to see why this is valid: foo() is already implemented by Super, and that implementation is inherited by Sub.
The exact rule goes like this:
Unless the class being declared is abstract, all the abstract member
methods of each direct superinterface must be implemented (§8.4.8.1)
either by a declaration in this class or by an existing method
declaration inherited from the direct superclass or a direct
superinterface, because a class that is not abstract is not permitted
to have abstract methods (§8.1.1.1).
While the rule only talks about direct superclasses, it is technically also true for indirect superclasses, as method inheritance bubbles down through the hierarchy.
Given that equals() is implemented by Object and Object is the direct or indirect superclass of every class, you don't have to provide an implementation for equals().

Must abstract methods be given a definition in a class or in an interface?

I thought in an interface, we usually explain what the method will do. And then in a class which implements the interface, we just write the implementation for the method. So, I thought we will provide the definition for an abstract method in the interface, but I am not sure. If you know the answer, please explain in in detail.
Definition and implementation are synonymous. A method's definition is its implementation.
Abstract methods don't have definitions/implementations, they are only declared. A declaration lists the method's name, parameters, and return type, but does not include the method body.
interface I {
// Declaration
void method(int arg);
}
class C implements I {
// Definition
public void method(int arg) {
System.out.println(arg);
}
}
An interface defines the required behavior of classes that implement it. The interface is meant to define:
The signature of the method
What the method's result is
You can imagine the interface as the "user-side" of the implementation. The user wants to know: What does this method do? What can I expect? How do I call it? The user doesn't care how it's done, only that he gets the expected result.
Implementing method define the implementation of the method. It's the class's job to figure out how the goal is going to be accomplished. Different implementing classes can achieve the same result using different means.
Thus, to summarize, the interface defines the method signature, and the implementing class defines the method body.
Definition is the same as implementation. In an interface, you only declare the abstract method. That means you specify the signature of the method, and what it returns. You do not define, how it works.
For eg
public interface Draw
{
public void drawCircle(int radius);
}
Here we only declare drawCircle() method, specifying what are the input parameters and what will be the output.
The actual implementation is specified in the class implementing the interface
public class DrawTool implements Draw
{
public void drawCircle(int radius)
{
// Give the logic for drawing Circle.
}
}
So here you are defining the Abstract Method drawCircle() in the class, the logic for drawing the circle.

Why are class static methods inherited but not interface static methods?

I understand that in Java static methods are inherited just like instance methods, with the difference that when they are redeclared, the parent implementations are hidden rather than overridden. Fine, this makes sense. However, the Java tutorial notes that
Static methods in interfaces are never inherited.
Why? What's the difference between regular and interface static methods?
Let me clarify what I mean when I say static methods can be inherited:
class Animal {
public static void identify() {
System.out.println("This is an animal");
}
}
class Cat extends Animal {}
public static void main(String[] args) {
Animal.identify();
Cat.identify(); // This compiles, even though it is not redefined in Cat.
}
However,
interface Animal {
public static void identify() {
System.out.println("This is an animal");
}
}
class Cat implements Animal {}
public static void main(String[] args) {
Animal.identify();
Cat.identify(); // This does not compile, because interface static methods do not inherit. (Why?)
}
Here's my guess.
Since Cat can only extend one class if Cat extends Animal then Cat.identify has only one meaning. Cat can implement multiple interfaces each of which can have a static implementation. Therefore, the compiler would not know which one to choose?
However, as pointed out by the author,
Java already has this problem, with default methods. If two interfaces
declare default void identify(), which one is used? It's a compile
error, and you have to implement an overriding method (which could
just be Animal.super.identify()). So Java already resolves this
problem for default methods – why not for static methods?
If I was to guess again, I'd say that with default the implementation is part of Cat's vtable. With static it cannot be. The main function must bind to something. At compile time Cat.identify could be replaced with Animal.identify by the compiler but the code wouldn't match reality if Cat was recompiled but not the class that contains main.
Before Java 8, you couldn't define static methods in an interface. This is heavily discussed in this question. I'm going to refer to this answer (by user #JamesA.Rosen) as to why the Java designers probably didn't want static methods in an interface initially:
There are a few issues at play here. The first is the issue of
declaring a static method without defining it. This is the difference
between
public interface Foo {
public static int bar();
}
and
public interface Foo {
public static int bar() {
...
}
}
Java doesn't allow either, but it could allow the second. The first is
impossible for the reasons that Espo mentions: you don't know which
implementing class is the correct definition.
Java could allow the latter, as long as it treated Interfaces as
first-class Objects. Ruby's Modules, which are approximately
equivalent to Java's Interfaces, allow exactly that:
module Foo
def self.bar
...
end
end
However, since the release of Java 8, you can actually add default and static methods inside an interface.
I'm going to be quoting this source a lot here. This is the initial problem:
Java's interface language feature lets you declare interfaces with
abstract methods and provide implementations of those methods in the
classes that implement the interfaces. You are required to implement
each method, which is burdensome when there are many methods to
implement. Also, after publishing the interface you cannot add new
abstract methods to it without breaking source and binary
compatibility.
This was the solution Java 8 provided default:
Java 8 addresses these problems by evolving the interface to support
default and static methods. A default method is an instance method
defined in an interface whose method header begins with the default
keyword; it also provides a code body. Every class that implements the
interface inherits the interface's default methods and can override
them
And for static:
A static method is a method that's associated with the class in which
it's defined, rather than with any object created from that class.
Every instance of the class shares the static methods of the class.
Java 8 also lets static methods be defined in interfaces where they
can assist default methods.
When you implement an interface that contains a static method, the
static method is still part of the interface and not part of the
implementing class. For this reason, you cannot prefix the method with
the class name. Instead, you must prefix the method with the interface
name
Example:
interface X
{
static void foo()
{
System.out.println("foo");
}
}
class Y implements X
{
}
public class Z
{
public static void main(String[] args)
{
X.foo();
// Y.foo(); // won't compile
}
}
Expression Y.foo() will not compile because foo() is a static member
of interface X and not a static member of class Y.
Static methods in interfaces could create a diamond of death if they were being inherited. So, calling a static method from the appropriate interface is good enough compared to the risk of calling it from a concrete class that may implement multiple interfaces that contain static methods of the same name.
Why are static methods any different?
Static methods are just functions unrelated to the objects. Instead of placing them in utility abstract classes (like calling Collections.sort() ) we move those functions (static methods) to their appropriate interfaces. They could be bound to the inherited objects like the default methods do, but that is not their job.
Static methods provide functionality which is unrelated to the instances of the class.
Example:
interface Floatable {
default void float() {
// implementation
}
static boolean checkIfItCanFloat(Object fl) {
// some physics here
}
}
class Duck implements Floatable { }
So, the point is that a Duck may float but the function that checks if an Object really floats is not something that a Duck can do. It is an irrelevant functionallity that we could pass to our Floatable interface instead of having it sit inside some utility class.
Let's begin with some background ...
Java doesn't support multiple inheritance (the ability to extend more than one class). This is because multiple inheritance is prone to the deadly diamond of death (also known as the diamond problem) which the designers of Java chose to preempt.
If B and C override a method inherited from A, which method does D inherit?
A class can implement multiple interfaces because interface methods are contracted for overriding; if a class C implements two interfaces A and B that declare the same method, then the same method in C will be invoked by clients of either interface (A or B). The introduction of default methods for interfaces in Java 8 was made possible by forcing the implementer to override the default in case of ambiguity. This was an acceptable compromise since default methods are intended to be defensive (to be used if no other implementation is explicitly provided by an implementer). However, since the compiler can’t force you to override a static method (static methods inherently can't be overridden), the introduction of static methods for interfaces in Java came with one restriction: the static methods of an interface are not inherited.
The answer is that static methods belong to a class/interface and there is only one instance for static blocks. that's the reason you can't override any static method.
Even in classes, you may override but only the super class' static method gets executed.

Java method that accepts references to interface objects

I'm kinda unsure about the following question:
If Launchable is a Java interface, what objects can be passed into the following method? What methods could be invoked on item inside this method?
public void prepareForLaunch (Launchable item) {
// some code
}
My current answer is:
From the above information, the only objects that can be passed into the method are objects that where instantiated as subclass types of the interface Launchable.(?) The methods that could be invoked on item inside the method would have to be public methods or protected methods within the same package. These methods would also have to be to be intended for a subclass of Launchable object since it is only in abstract and actual(concrete) classes where a method body’s definition can exist.
I was wondering if someone here can check my answer and add any suggestions. Thanks!
You can only pass in instances of classes that implement Launchable (either directly, or by inheritance from a superclass). You can also pass in null.
Inside of the method, you can call all the methods defined in Launchable (and in Object).
These methods would be defined in the Launchable interface, but implemented in the actual class (a fact that is guaranteed by the Java type system, which won't let you have classes with incomplete interface implementations, those would need to be declared abstract and cannot be instantiated).
If you need to call any other methods you need to know that the object in question also implements some other interface (or is of a given class), and do a typecast to that first.
Since you stated that Launchable is an interface, an instance of any class that implements Launchable could be passed to prepareForLaunch. Any class implementing Launchable would have to implement the methods defined in the interface and thus any method of Launchablecould be invoked to objects given to prepareForLaunch.
You are right about the first part. About the methods you can invoke: If you are not using casting then you can only invoke public\protected within the same package of Launchable. If you will use casting you can extend the range of the methods you can invoke to the methods in the casted-to class.
Consider this code:
public interface Launchable
{
public void aMethod();
}
public class SomeClass implements Launchable
{
public void aMethod()
{
}
public void bMethod(){}
}
Without casting youll be able to call
item.aMethod();
With Casting youll be able to call:
((SomeClass)item).bMethod();
you should use implements statement ,
public void prepareForLaunch() implements Launchbla {
}

Categories