Using Clone() with polymorphism from interface in java - java

I am having problems trying to figure out how to call the clone method from a object which its reference is of an interface type.
Basically this is what I need to do.
for(Interface obj: objs)
array.add(obj.clone());
I do not know what is the obj type, I just know it implements Interface, and when I try this code I get
"The method clone() is undefined for the type Interface".
And when I try to put clone() on my Interface I get:
"The method clone() of type Interface must override or implement a supertype method", because I am using #Override tag.
My intention is to use Object.clone() in the end. But I just cant figure this out.
Any thoughts?
The real code:
public interface Caracteristica {
#Override <---problem
public Object clone() throws CloneNotSupportedException;
#Override <---fine
public boolean equals(Object obj);
}
private final void setCaracteristicas(ArrayList<Caracteristica> caracteristicas) {
this.caracteristicas = new ArrayList<>();
for(Caracteristica caracteristica: caracteristicas)
this.caracteristicas.add((Caracteristica)caracteristica.clone());
}

Basically, clone() and the Cloneable interface is broken in a number of ways and even according to Josh Bloch it should be avoided. (See: http://www.artima.com/intv/bloch13.html)
Add a new method to your interface that returns the interface type and implement that in your class to make copies.
Edit to Add: Ignoring the above statement, the reason it is telling you that the #Override annotation in your interface is incorrect is because ... it is. You're not extending an interface that defines clone().
Interfaces don't extend Object; Section 9.2 of the JLS tells us:
If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless a method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface.
clone() is protected in Object so it is not implicitly included. If your IDE said to add the #Override tag, report that as a bug, because it's wrong.
equals(), on the other hand, is public in Object, therefore it is included in the implicit superinterface unless you override it.
If you are bound and determined, this will work though it's really ugly due to the confusion created by clone() being defined both in Object and MyInterface and having it return the interface type (which is allowed because it's a covariant type):
public interface MyInterface {
MyInterface clone();
void doSomething();
}
public class MyClass implements MyInterface {
#Override
public void doSomething() {
System.out.println("Hi");
}
#Override
public MyInterface clone() {
return new MyClass();
}
public static void main(String[] args) {
MyInterface mi = new MyClass();
MyInterface mi2 = mi.clone();
mi2.doSomething();
}
}

Object.clone() is protected, you can't call it from outside the class or its subclasses unless they explicitly change the access modifier to public thus there is no guarantee an object has a visible clone() method.
You have to define this in an interface or override it in a baseclass instead.

Related

toString,hashcode and equals method inside interface

Below example runs without any errors, can any one explain me how this works?, as interface doesn't contain any toString()/hashcode/equals method declaration how compiler will resolve method call?,as per my understanding toString()/hashcode/equals or Object class methods will be declared by default inside interface? please correct me if am wrong
interface int1
{
public void show();
}
class inttest implements int1
{
public void show()
{
System.out.println("inttest.show()");
}
#Override
public String toString()
{
return "tostring called";
}
}
public class MainClass1
{
public static void main(String[] args) {
int1 i=new inttest();
System.out.println(i.toString());
}
}
Any interface has all the public methods of the Object class (it either inherits them from a super-interface or declares them implicitly if it doesn't already declare them explicitly).
This makes sense, since any implementing class of any interface must be a (direct or in-direct) sub-class of the Object class, and therefore will inherit an implementation of all the Object methods.
9.2. Interface Members
If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless an abstract method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface.
As all objects extend Object and Object has a toString() you are calling that method.

How Interface have accessibility to Object class methods?

I got the below info from Oracle docs:
If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless a method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface.
can someone tell me how an interface is able to implicitly declare public abstract methods to each and every public instance methods which are not-final avaliable in Object class ?
interface Test {
public void functionA();
}
class child implements Test{
public void functionA() {
}
public static void main(String[] args) {
Test test = new child();
test.toString(); // since toString is Objects class method, How it's visible for Test interface ref?
}
}
how an interface is able to implicitly declare public abstract methods to each and every public instance methods which are not-final avaliable in Object class ?
An interface isn't able to do this -- only a concrete object can. My guess is that you're looking at code that shows creation of an anonymous inner class from an interface and think that this is instantiation of the interface -- but it isn't. Rather it's a concrete class, one without a name, that implements the interface, and that extends from Object, as all concrete classes do.
And now I'm not so sure as this compiles:
public interface MyInterface {
void foo();
#Override
String toString();
#Override
boolean equals(Object o);
}
The correct answer may be: because that is how the authors of Java willed it to be.
How Interface have accessibility to Object class methods?
As always, the answer is in the JLS:
4.10.2. Subtyping among Class and Interface Types
Given a non-generic type declaration C, the direct supertypes of the type C are all of the following:
The direct superclass of C (§8.1.4).
The direct superinterfaces of C (§8.1.5).
The type Object, if C is an interface type with no direct superinterfaces (§9.1.3).
So the 3rd point answers your question. As a subtype of Object, the interface inherits its methods.
Note: this is true also for generic interfaces (explained in the rest of 4.10.2).

How it is possible to call methods of Object class on a reference of Interface type?

interface TestInterface{
public void sayHello();
}
class A implements TestInterface{
public void sayHello(){
System.out.println("Hello");
}
public void sayBye(){
System.out.println("Hello");
}
public String toString(){
return "Hello";
}
public static void main(String args[]){
TestInterface ti=new A();
ti.sayHello();
ti.sayBye();//error
ti.toString();//How toString method can be called as it is not the part of the interface contract.
}
}
From this section in the Java Language Specification:
If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless an abstract method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface.
So Object's public methods like toString are implicitly declared in all interfaces.
toString can be called because any implementation of any interface must be a sub-class of Object, which contains the toString method.
In order to call any other method that doesn't appear in the interface or in any super-interface your interface extends (and is not defined in Object class), you must cast the interface to the type of the class that contains that method.
Every object is an Object :) It would make sense to call Object methods on objects.
That's the heart of the matter - all reference types are subtypes of Object. Reference types include
class type
interface type
array type
type variable (T)
null type (for null)
intersection type ( A&B )
A subtype inherits methods from the supertype. Therefore all reference types inherit Object methods.
This is the nature of OO Languages. Interfaces only define a set of method signatures that a concrete class needs to implements. They don't restrict the nature of the class (abstract v concrete).
So when you declare TestInterface ti, in your example A implements TestInterface, so it is an instance of TestInterface. Likewise class B implements TestInterface {...} is also valid.
TestInterface ti = new A(); // Valid
ti = new B(); // Also valid (given the above definition)

Polymorhism and the class Object

We know that each class extends from Object which means that we can use all Object's methods
in any class. My problem is the following:
interface B{
}
public class A implements B{
public static void main(String[] args){
B i = new A();
i.display();//we can't do this : because the interface B doesn't define such a method
System.out.println(i.toString());// we can do this although the interface doesn't extend from Object
}
public void display(){
}
}
so I think the problem is clear , why I could invoke the toString method although the interface B can't extend from Object?
This is spelled out in the JLS §9.2. Interface Members:
If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless an abstract method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface.
This ensures that it is possible to call Object methods via any interface.

Overriding Object class methods within an interface in Java

Let's consider the following simple code in Java.
package temppkg;
interface Interface
{
#Override
public abstract boolean equals(java.lang.Object arg);
#Override
public abstract String toString();
public void show();
}
final class Demo implements Interface
{
public void show()
{
System.out.println("Method invoked.");
}
}
final public class Main
{
public static void main(String...args)
{
new Demo().show();
}
}
In the above code snippet, the interface named Interface has some Object class methods from JDK and they are with the #Override annotation even though they are abstract. Now, the class Demo has implemented Interface and has not implemented the equals() and the toString(); methods. Still the compiler doesn't complain and the program is running successfully. Why?
What is the relation between interfaces and the object class in Java?
The Java Language Specification clearly says that the members of an
interface are those which are declared in the interface and those
which are inherited from direct super interfaces. If an interface has
no direct superinterface then the interface implicitly declares a
public abstract member method corresponding to each public instance
method declared in the Object class, unless a method with the same
signature, same return type, and a compatible throws clause is
explicitly declared by that interface. This is what makes the
signatures of the Object methods available to the compiler and the
code compiles without any error. Remember if the interface tries to
declare a public instance method declared 'final' in the Object class
then it'll result into a compile-time error. For example, 'public
final Class getClass()' is a public instance method declared 'final'
in the Object class and therefore if an interface tries to declare a
method with this signature then the compilation will fail.
http://geekexplains.blogspot.com/2008/06/do-interfaces-really-inherit-from-class.html
Check out JLS 9.2:
If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless a method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface. It is a compile-time error if the interface explicitly declares such a method m in the case where m is declared to be final in Object.
In other words, every interface implicitly defines each of Object's methods, and you can therefore #Override those methods. The other methods aren't defined in Object, so you can't override them.
In Interface you're not actually overriding anything - an interface by definition can not provide implementations for any of its methods. The class Demo just inherits the equals and toString implementation from Object.
In essence an interface in Java contains a set of zero or more method signatures (all of them are implicitly abstract, in your code you made it explicit by adding the keyword abstract), and the concrete classes that implement the interface must provide an implementation for those methods. In the case of your code, that implementation comes from Object, since all the classes implicitly extend Object, which provides default implementations for equals and toString (among other methods).
You really shouldn't mark the methods in an interface with #Override, as you have seen, it's confusing and serves for no practical purpose. Instead, use #Override in the methods in the concrete class that implement the methods of the interface, like this:
class Demo implements Interface {
#Override
public void show() {
System.out.println("Method invoked.");
}
}
Also, it's completely unnecessary to declare equals and toString in an interface, so you're better off with this definition:
interface Interface {
public void show();
}
#Override can only be used for functions defined in the base class, Object. Object defines equals and toString, so you can use #Override with them, but not with, say, the function show. It indicates a relationship between the #Override functions in a class and its base classes, not it's derived classes.

Categories

Resources