抽象成员不能直接访问:Kotlin
我有接口A与实施的方法t()
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的执行中删除它的工作。
谁能解释为什么?
在kotlin中没有引用,但是方法调用表达式 TypeName.super. [TypeArguments] Identifier ( [ArgumentList] )
.super TypeName.super. [TypeArguments] Identifier ( [ArgumentList] )
TypeName.super. [TypeArguments] Identifier ( [ArgumentList] )
在JLS-15.12.3中有详细描述:
注意 :这里的interface
是一个class
/ interface
。
如果TypeName表示一个接口 ,那么让
T
是立即封装方法调用的类型声明。 如果存在一种与编译时声明不同的方法 , 会覆盖 (§9.4.1)T
的直接超类或直接超接口的编译时声明,则会发生编译时错误。在超级接口 (类
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的规则,如果您不让C
类直接实现A
,则您也无法访问祖父接口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;
当class B
叫做interface A
,应该在接口中实现这个功能,但是并没有这样做。 相反,它“承诺”(通过使用abstract
关键字)将该实现留给任何继承它的类, interface A
同意。 现在,当class C
进入时,它调用了function B
和interface 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() } }
或者帮助B班付钱,就像这样:
open class C: B(){ override fun t(): String { return super.t() } }
它不能这样做,因为这将创建具有相同签名的两个函数。 希望这个比喻帮助你理解。