Types 为什么带有私有setter的var是不变位置?

Types 为什么带有私有setter的var是不变位置?,types,kotlin,covariance,Types,Kotlin,Covariance,(我使用kotlin 1.1.2-2) 我发现有两种方法可以定义可变但无法通过=分配的属性 var与私有setter val带有私有变量支持属性 我还发现他们有不同的行为 当T被声明为out时,不能定义带有私有setter的T类型的var,而带有backing属性的val是合法的 open class A<out T>(v: T) { // error because T occurs in invariant position var prop1: T = v

(我使用kotlin 1.1.2-2)

我发现有两种方法可以定义可变但无法通过
=
分配的属性

  • var
    与私有setter
  • val
    带有私有变量支持属性
  • 我还发现他们有不同的行为

    T
    被声明为
    out
    时,不能定义带有私有setter的
    T
    类型的
    var
    ,而带有backing属性的
    val
    是合法的

    open class A<out T>(v: T) {
        // error because T occurs in invariant position
        var prop1: T = v
        private set
    
        private var _prop: T = v
        val prop2: T get() = _prop
    }
    
    开放式A类(v:T){
    //错误,因为T出现在不变位置
    变量1:T=v
    专用设备
    私有var_prop:T=v
    val prop2:T get()=\u prop
    }
    

    为什么
    prop1
    是不变位置而
    prop2
    不是不变位置?差异从何而来?

    在您的案例中,您声明的
    私有var
    可以工作是,您不能将其从类
    A
    中更改,因为它是
    私有的
    ,并且您不能为修改目的声明带有
    输出方差的函数

    private var
    private set
    之间的区别在于
    private
    变量没有getter/setter,只是在java中生成了一个字段。但是
    private set
    属性具有getter/setter,并且setter是
    private

    out
    方差仅适用于读取模式,这意味着您不能在其中添加任何内容。它的实际类型是
    T
    ,或
    ?在java中扩展T

    因为
    out
    变量的写入模式等同于
    Nothing
    ,所以您根本不能声明
    setter
    /mutable变量。但您可以使用不可变属性引用它,例如:

    open class A<out T>(v: T) {
     //v--- immutable
      val prop1: T = v
    
    }
    
    也许下面的示例会让您更清楚地了解为什么不能在
    out
    方差参数中添加任何内容

    val int: A<Int> = A(1) // ok
    
    val number: A<Number> = int; //ok
    
    number._prop = 1.0; 
    //     ^
    //if you can define setter/mutable variable, you try to assign a Double into a Int 
    
    val int:A=A(1)//确定
    val编号:A=int//好啊
    数量._prop=1.0;
    //     ^
    //如果可以定义setter/mutable变量,那么可以尝试将Double赋值到Int中
    
    没有getter/setter似乎是一个次要的实现细节,不足以解释类型系统中的差异semantics@voddan是的,先生。事实上,这种行为在kotlin中应该被禁止。没有必要禁止它。Kotlin意识到允许
    private var prop:T
    ,其中
    T
    是协变(
    out
    )类型参数可能会导致类型系统冲突,因此这些属性被视为“对此私有”,例如,只允许类在自己的实例上更改它们。@RomanElizarov hi,正如您所说,它可以在自己的实例中更改,因此应该禁止这种行为。假设您有一个可以在内部更改的函数,例如:
    \u prop=1 as T
    ,如果
    T
    不是
    Int
    ,则代码不可靠。请提供一个自包含的示例,演示由于协变类型的可变属性而导致的类型系统冲突?我看得越久,对我来说,它越像一个bug:/1尝试为prop1变量添加“private get”,然后再次检查。“私有集”可能会添加一个不一致的对象,该对象将在类之外返回。
    val int: A<Int> = A(1) // ok
    
    val number: A<Number> = int; //ok
    
    number._prop = 1.0; 
    //     ^
    //if you can define setter/mutable variable, you try to assign a Double into a Int