- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
更新 2020-12-23
起源描述有点困惑。 Kotlin 不仅允许在子类中使用 getter 相同的签名,而且在自类中也允许使用相同的签名。所以这也是允许的:
open class BaseRequest {
val params = mutableMapOf<String, String>()
fun getParams(): List<String> {
return params.values.toList()
}
}
正如@Slaw 所说,这是 kotlin 编译器的行为,并且它可以工作,因为 JVM 使用地址而不是“签名”调用正确的方法。
open class BaseRequest {
val params = mutableMapOf<String, String>()
init {
params["key1"] = "value1"
}
}
class SpecificRequest : BaseRequest() {
init {
params["key2"] = "value2"
}
fun getParams(): List<String> {
return params.values.toList()
}
}
MediatorRequest 有一个函数
getParams()
它与它的父类(super class)具有相同的签名但具有不同的返回类型。在使用这个函数时,子类和父类(super class)似乎有相同声明的不同实现。
fun main() {
val specificRequest = SpecificRequest()
println("specificRequest.params: ${specificRequest.params}")
println("specificRequest.getParams(): ${specificRequest.getParams()}")
println("(specificRequest as BaseRequest).params: ${(specificRequest as BaseRequest).params}")
}
输出将是这样的:
specificRequest.params: {key1=value1, key2=value2}
specificRequest.getParams(): [value1, value2]
(specificRequest as BaseRequest).params: {key1=value1, key2=value2}
如果我们查看反编译的Java代码,有两个方法具有相同的签名和不同的返回类型,这在Java中确实是不允许的。
public class BaseRequest {
@NotNull
private final Map params;
@NotNull
public final Map getParams() {
return this.params;
}
/* ... */
}
public final class SpecificRequest extends BaseRequest {
@NotNull
public final List getParams() {
return CollectionsKt.toList((Iterable)this.getParams().values());
}
/* ... */
}
我知道函数名不合适,但存在潜在风险,如果我们在 .java 中使用 SpecificRequest,在将实例转换为它的父类(super class)之前,我们无法访问 Map 参数。这可能会导致误解。
最佳答案
Java 语言和 JVM 之间存在差异。 Java 语言不允许在同一个类中声明两个名称相同但返回类型不同的方法。这是语言的限制。然而,JVM 完全有能力区分这两种方法。而且由于 Kotlin 是它自己的语言,因此它不必遵循与 Java 完全相同的规则——即使是针对 JVM(因此编译为字节码)。
考虑以下 Kotlin 类:
class Foo {
val bar = mapOf<Any, Any>()
fun getBar() = listOf<Any>()
}
如果你编译这个类然后用
javap
检查字节码你会看到的:
Compiled from "Foo.kt"
public final class Foo {
public final java.util.Map<java.lang.Object, java.lang.Object> getBar();
public final java.util.List<java.lang.Object> getBar();
public Foo();
}
所以这两个函数肯定存在,尽管名称相同。但是,如果您访问该属性并调用该函数,您将看到:
fun test() {
val foo = Foo()
val bar1 = foo.bar
val bar2 = foo.getBar()
}
变成:
public static final void test();
descriptor: ()V
flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
Code:
stack=2, locals=3, args_size=0
0: new #8 // class Foo
3: dup
4: invokespecial #11 // Method Foo."<init>":()V
7: astore_0
8: aload_0
9: invokevirtual #15 // Method Foo.getBar:()Ljava/util/Map;
12: astore_1
13: aload_0
14: invokevirtual #18 // Method Foo.getBar:()Ljava/util/List;
17: astore_2
18: return
这表明字节码知道要调用哪个函数。 JVM 可以处理这个问题。
class Foo {
fun getBaz() = mapOf<Any, Any>()
fun getBaz() = listOf<Any>()
}
为什么?我并不乐观,但我相信这与语法有关。 Kotlin 编译器总是可以根据您是否使用
foo.bar
轻松判断您打算调用哪个函数。或
foo.getBar()
.但是调用两个
getBaz()
的语法是一样的函数,这意味着编译器无法轻易分辨出您打算在所有情况下调用哪个函数(因此它不允许上述情况)。
关于Kotlin 允许与具有不同返回类型的属性 getter 相同的函数签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65421518/
你能比较一下属性吗 我想禁用文本框“txtName”。有两种方式 使用javascript,txtName.disabled = true 使用 ASP.NET, 哪种方法更好,为什么? 最佳答案 我
Count 属性 返回一个集合或 Dictionary 对象包含的项目数。只读。 object.Count object 可以是“应用于”列表中列出的任何集合或对
CompareMode 属性 设置并返回在 Dictionary 对象中比较字符串关键字的比较模式。 object.CompareMode[ = compare] 参数
Column 属性 只读属性,返回 TextStream 文件中当前字符位置的列号。 object.Column object 通常是 TextStream 对象的名称。
AvailableSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。 object.AvailableSpace object 应为 Drive 
Attributes 属性 设置或返回文件或文件夹的属性。可读写或只读(与属性有关)。 object.Attributes [= newattributes] 参数 object
AtEndOfStream 属性 如果文件指针位于 TextStream 文件末,则返回 True;否则如果不为只读则返回 False。 object.A
AtEndOfLine 属性 TextStream 文件中,如果文件指针指向行末标记,就返回 True;否则如果不是只读则返回 False。 object.AtEn
RootFolder 属性 返回一个 Folder 对象,表示指定驱动器的根文件夹。只读。 object.RootFolder object 应为 Dr
Path 属性 返回指定文件、文件夹或驱动器的路径。 object.Path object 应为 File、Folder 或 Drive 对象的名称。 说明 对于驱动器,路径不包含根目录。
ParentFolder 属性 返回指定文件或文件夹的父文件夹。只读。 object.ParentFolder object 应为 File 或 Folder 对象的名称。 说明 以下代码
Name 属性 设置或返回指定的文件或文件夹的名称。可读写。 object.Name [= newname] 参数 object 必选项。应为 File 或&
Line 属性 只读属性,返回 TextStream 文件中的当前行号。 object.Line object 通常是 TextStream 对象的名称。 说明 文件刚
Key 属性 在 Dictionary 对象中设置 key。 object.Key(key) = newkey 参数 object 必选项。通常是 Dictionary 
Item 属性 设置或返回 Dictionary 对象中指定的 key 对应的 item,或返回集合中基于指定的 key 的&
IsRootFolder 属性 如果指定的文件夹是根文件夹,返回 True;否则返回 False。 object.IsRootFolder object 应为&n
IsReady 属性 如果指定的驱动器就绪,返回 True;否则返回 False。 object.IsReady object 应为 Drive&nbs
FreeSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。只读。 object.FreeSpace object 应为 Drive 对象的名称。
FileSystem 属性 返回指定的驱动器使用的文件系统的类型。 object.FileSystem object 应为 Drive 对象的名称。 说明 可
Files 属性 返回由指定文件夹中所有 File 对象(包括隐藏文件和系统文件)组成的 Files 集合。 object.Files object&n
我是一名优秀的程序员,十分优秀!