gpt4 book ai didi

kotlin - 父类中 protected 内联方法不能访问其他 protected 方法

转载 作者:行者123 更新时间:2023-12-02 12:52:37 27 4
gpt4 key购买 nike

我在获取 时遇到问题非法访问错误 对于以下示例:

我在名为 arch 的 gradle 模块中声明了一个基类

abstract class BaseClass {
protected abstract val value: Int

fun run() {
Log.d("Printme", "value $value")
}

protected inline fun getMyValue(): Lazy<Int> = lazy {
getAnEight()
}

protected fun getAnEight() = 8
}

以及在 gradle 模块中声明的子类 app
class ChildClass: BaseClass() {
override val value by getMyValue()
}

值得一提的是,我正在使用 Android Studio 创建一个 Kotlin 项目,但是这些类都是简单的 Kotlin 对象,没有任何 Android 特定的引用。当然这两个模块也有不同的包。

现在,从我的主要输入方法中,我正在执行以下操作(在 app 模块内)
ChildClass().run()

我调用我的 run()在基类中声明的方法,它正在访问延迟启动的 value属性,依次调用 getAnEight()方法。由于所有方法都受到保护,我希望子类没有理由不能调用所有这些方法。即使其中一种方法被标记为 inline并且此调用被方法内容替换,它应该仍然可以调用 getAnEight()正好。

相反,我收到 IllegalAccessErrorBaseClass.getAnEight() is inaccessible to class ChildClass$$special$$inlined$getMeValue$1 .删除 inline 后,此问题消失修饰符,或者如果我放置 BaseClassChildClass 在同一个包中.

这是 Kotlin 编译器中的错误吗?或者如果它按预期工作,有人可以向我解释这种行为吗?提前致谢!

最佳答案

https://kotlinlang.org/docs/reference/inline-functions.html#public-inline-restrictions

When an inline function is public or protected and is not a part of a private or internal declaration, it is considered a module's public API. It can be called in other modules and is inlined at such call sites as well.

This imposes certain risks of binary incompatibility caused by changes in the module that declares an inline function in case the calling module is not re-compiled after the change.

To eliminate the risk of such incompatibility being introduced by a change in non-public API of a module, the public API inline functions are not allowed to use non-public-API declarations, i.e. private and internal declarations and their parts, in their bodies.

An internal declaration can be annotated with @PublishedApi, which allows its use in public API inline functions. When an internal inline function is marked as @PublishedApi, its body is checked too, as if it were public.



编辑:我做了一些字节码研究。问题是 protected getMyValue() 函数是内联的 进入公共(public)构造函数 .在反编译的字节码中,ChildClass 公共(public)构造函数有以下一行:
Lazy var4 = LazyKt.lazy((Function0)(new ChildClass$$special$$inlined$getMyValue$1(this)));

如您所见,它创建了一个类 ChildClass$$special$$inlined$getMyValue$1 的实例。 .让我们看看它的声明:
public final class ChildClass$$special$$inlined$getMyValue$1 extends Lambda implements Function0 {

final BaseClass this$0;

public ChildClass$$special$$inlined$getMyValue$1(BaseClass var1) {
super(0);
this.this$0 = var1;
}

public Object invoke() {
return this.invoke();
}

public final int invoke() {
return this.this$0.getAnEight(); // Here lies the problem
}
}

当你创建一个 ChildClass 实例时,它的构造函数只创建一个 ChildClass$$special$$inlined$getMyValue$1例如,这不会引发任何错误。但是当你调用 run() 时, invoke()上面类的方法被调用。这个方法是公共(public)的,它的类是公共(public)的,构造函数是公共(public)的,但是 getAnEight 方法是 protected 。这就是我们得到这个错误的方式。

关于kotlin - 父类中 protected 内联方法不能访问其他 protected 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59752358/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com