A
A
Artem Parfenov2013-10-22 11:55:21
Java
Artem Parfenov, 2013-10-22 11:55:21

Java - Implementing Parameterized Interfaces

Greetings to all Java learners!
The other day, picking Eckel on a cold autumn evening (Thinking in Java 4ed), I finally got confused in everything. Reading a short paragraph:

Implementing Parameterized Interfaces A
class cannot implement two flavors of the same parameterized interface—due to erasure, they will be considered the same interface. An example of this kind of conflict:
interface Payable<T> {}

class Employee implements Payable<Employee> {}
class Hourly extends Employee implements Payable<Hourly> {}

The Hourly class won't compile because erasing reduces Payable<Employee> и Payable<Hourly>it to Payable, which in the example above would mean implementing the same interface twice. An interesting detail: if you remove parameterized arguments from both mentions of Payable, as the compiler does when deleting, the program will compile.
I’ll make a reservation right away - the situation is not combat, I just want to deal with the theory normally.
Of course I suspected something was wrong, I quickly threw in the source code in Eclips`e ... it works, dog, as it is said.
If you start cleaning the herring from the tail, so to speak, then there are simply no questions to the last statement:
if you remove parameterized arguments from both mentions of Payable, as the compiler does when erasing, the program will compile
That is, it will be:
class Employee implements Payable {}
class Hourly extends Employee implements Payable {}
OK, everything is fine, the interface is the same, interfaces are not inherited, which means that you can implement the same interface as much as you like in the inheritance hierarchy.
We clean the belly of the herring:
… erasing reduces Payable<Employee>it Payable<Hourly>to Payable…
ok, a little tighter. Erasure does not allow getting type information inside the parameterized code, the compiler generates the usual NON-parameterized bytecode. Well, they are Payable<Employee> и Payable<Hourly>erased to the nearest restriction (and we have no restrictions on the type parameter - interface Payable<T> {}) or to the “low-level” Payable type.
Approaching the head of the herring:
A class cannot implement two flavors of the same parameterized interface - due to erasure, they will be considered the same interface
well, that's great, the compiler will simply erase to Payable and that's it Payable<Employee>. Payable<Hourly>Obviously not all. And finally, a completely incomprehensible phrase:
... in the example above, this would mean implementing the same interface twice.
How is this to be understood?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
B
becevka, 2013-10-22
@becevka

Here is a piece of code for meditation:

    interface Payable<T> {
        void doIt(T t);
    }

    class Employee implements Payable<Employee> {
        @Override
        public void doIt(Employee t) {}
    }
    
    class Hourly extends Employee implements Payable<Hourly> {
        //что реализовать?
        @Override
        public void doIt(Employee t) {}
        // или
        @Override
        public void doIt(Hourly t) {}
    }

K
Kaigorodov Alexey, 2013-10-22
@rfq

For complex cases, refer to the original source: Chapter 8. Classes , where it says:
A class may not at the same time be a subtype of two interface types which are different invocations of the same generic interface (§9.1.2), or a subtype of an invocation of a generic interface and a raw type naming that same generic interface, or a compile-time error occurs.
This requirement was introduced in order to support translation by type erasure (§4.6).
And if informally, then the meaning of the type parameters is to statically narrow the allowable types for different instances of the same class, so that the narrowing is different for different instances.
The code you provided uses two different narrowings: and :
class Employee implements Payable<Employee> {} class Hourly extends Employee implements Payable<Hourly> {}
which cannot be combined in one instance. Erasure here despite the fact that if it were not there, one could try to glue the interfaces and require two implementations of each method (IMHO, a bad idea), otherwise we have only one doIt method and two different signatures.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question