I have interface A with implemented method t()
interface A{
fun t() : String{
return "A"
}
}
And abstract class B
abstract class B : A{
override abstract fun t(): String
}
And one class C
open class C: A, B(){
override fun t(): String {
//return super<A>.t() // getting error
return super.t() //getting error here
}
}
I want to call interface function t() but its giving me error Abstract member cannot be access directly
If I remove implementation of A from B its working.
can anyone explain why?
There is no reference in kotlin, but the Method Invocation Expression TypeName.super. [TypeArguments] Identifier ( [ArgumentList] )
in java is described exactly in JLS-15.12.3:
Note: interface in here is a class
/ an interface
.
If TypeName denotes an interface, let
T
be the type declaration immediately enclosing the method invocation. A compile-time error occurs if there exists a method, distinct from the compile-time declaration, that overrides (§9.4.1) the compile-time declaration from a direct superclass or direct superinterface ofT
.In the case that a superinterface (class
B
) overrides a method declared in a grandparent interface (interfaceA
), this rule prevents the child interface from "skipping" the override by simply adding the grandparent to its list of direct superinterfaces. The appropriate way to access functionality of a grandparent is through the direct superinterface (classB
), and only if that interface chooses to expose the desired behavior. (Alternately, the developer is free to define his own additional superinterface that exposes the desired behavior with a super method invocation.)
So even if the t()
is a concrete method in class B
, it also failed in compile time, for example:
interface A {
fun t() = "A"
}
abstract class B : A {
override fun t() = "B"
}
class C : A, B() {
// v--- error
override fun t()= super<A>.t();
// v--- ok
fun ok()= super<B>.t();
}
Following the rule of the JLS-15.12.3 , you also can't access grandfather interface A
if you don't let class C
implements A
directly, for example:
// v-- grandparent interface A is removed from class C
class C : B() {
// v--- can't access the grandparent interface A
override fun t() = super<A>.t();
}
An abstract superinterface can re-declare a concrete method in its grandparent interface to an abstract method. but you must implements the abstract method in child class, for example:
interface GrandParent {
fun foo() = "bar";
}
interface Parent : GrandParent {
override fun foo(): String;
}
// v--- must implements abstract foo() method in Parent interface
class Child : Parent;
When class B
'called' the interface A
, it was supposed to implement the function in the interface but didn't do that. Instead, it 'promised' (by using the abstract
keyword) to leave that implementation to any class that inherits it, to which interface A
agreed. Now when class C
came in, it 'called' both function B
and interface A
and overrode a function t()
(a function both interface A and function B have). Now, the question is, which of function t()
is being overridden? You can't do that and that is why you have your error.
Or using another analogy, class B
is owing with interface A
. If class B
had paid interface A
, then it can help class C
settle it's debt with interface A
, like this:
interface A{
fun t():String{
return "A"
}
}
abstract class B :A{
override fun t():String{
return "potato"
}
}
open class C: A, B(){
override fun t(): String {
return super<B>.t()
}
But since that's not the case, class C
has to settle it's own debt with interface A
like this:
open class C: A {
override fun t(): String {
return super.t()
}
}
Or help class B pay his, like this:
open class C: B(){
override fun t(): String {
return super.t()
}
}
It can't do both because that will be creating two functions with the same signature. Hope this analogy helped you understand.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With