抽象成员无法直接访问:Kotlin

时间:2017-06-29 11:47:47

标签: java kotlin

我有实现方法t()

的接口A.
interface A{
    fun t() : String{
        return "A"
    }
}

抽象类B

abstract class B : A{
     override abstract fun t(): String
}

还有一个C类

open class C: A, B(){
    override fun t(): String {
        //return super<A>.t() // getting error
        return super.t() //getting error here 
    }
}

我想调用接口函数t(),但它给我错误抽象成员无法直接访问

如果我从B中移除A的实现,那么

任何人都可以解释原因吗?

2 个答案:

答案 0 :(得分:2)

class B被称为&#39; interface A,它应该在界面中实现该功能,但并没有这样做。相反,它承诺&#39; (通过使用abstract关键字)将该实现留给任何继承它的类,interface A同意。现在当class C进来时,它被称为“{1}}。 function Binterface A都覆盖了function t()(接口A和功能B都有的功能)。现在,问题是,function t()中的哪一个被覆盖了?你不能这样做,这就是你有错误的原因。

或者使用另一个类比,class B归于interface A。如果class B已付interface A,那么class C可以帮助interface A解决它与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() } 的债务,如下所示:

class C

但由于情况并非如此,interface A必须像open class C: A { override fun t(): String { return super.t() } } 那样解决它自己的债务:

open class C:  B(){
    override fun t(): String {
     return super.t()
    }

}

或帮助B班支付他的费用,如下:

html canvas

它无法做到这两点,因为这将创建具有相同签名的两个函数。希望这个比喻能帮助你理解。

答案 1 :(得分:2)

kotlin中没有引用,但java中的Method Invocation Expression TypeName.super. [TypeArguments] Identifier ( [ArgumentList] )完全在JLS-15.12.3中描述:

注意:此处的界面为class / interface

  

如果TypeName表示接口,则让T成为立即封闭方法调用的类型声明。如果存在一个方法(与编译时声明不同),覆盖(§9.4.1)直接编译时声明,则会发生编译时错误T的超类或直接超接口。

     

如果 superinterface (类B)覆盖祖父节点接口(接口A)中声明的方法,则此规则通过简单地将祖父表添加到其直接超接口列表中来阻止子接口“跳过”覆盖。 访问祖父母功能的适当方式是通过直接超级接口(类B),并且只有当该接口选择公开所需行为时。 (或者,开发人员可以自由定义自己的附加超接口,通过超级方法调用公开所需的行为。)

因此,即使t()是类B中的具体方法,它在编译时也会失败,例如:

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();

}

遵循JLS-15.12.3的规则,如果您不让类A直接实现C,则也无法访问祖父接口A,例如:

//       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(); 
}

抽象超接口可以在祖父节点接口中将一个具体方法重新声明为抽象方法。但是您必须在子类中实现抽象方法,例如:

interface GrandParent {
    fun foo() = "bar";
}

interface Parent : GrandParent {
    override fun foo(): String;
}

//     v--- must implements abstract foo() method in Parent interface
class Child : Parent;