当你有LET时,READ-only变量有什么意义?

时间:2016-11-16 16:22:21

标签: swift

例如:

var dogName : String {
 return "Buster"
}

VS ..

let dogName = "Buster"

假设我们将类中的每一个声明为实例属性。这些只是做同样事情的两种方式吗?如果没有,那么拥有只读变量有什么意义呢?

由于

5 个答案:

答案 0 :(得分:6)

让我试着总结其他答案所说的内容,同时添加我认为对于理解这一点至关重要的缺失信息。

属性

属性只是与对象关联的值,可以在很短的时间内查询,而不需要(或能力)方法等参数。

存储属性

当您创建存储属性时,无论是let还是var,在任何给定时间点分配的值都将存储在内存中,这就是它被称为存储属性的原因。 / p>

var name = "Matt"

对于使用var的变量,该值以一种使其可变(可编辑)的方式存储在内存中。您可以随意重新分配该值,它将替换之前的值存储在内存中

let name = "Matt"

对于使用let的常量,该值也会存储在内存中,但是在第一次分配后可能无法更改

计算属性

计算属性不存储在内存中。正如ganzogo在评论中所说,计算属性的行为与方法类似,但不采用参数。在决定何时使用计算属性或没有参数的函数时,Swift API设计指南建议在简单地创建或获取时使用计算属性,然后返回该值,前提是这需要花费很少的时间。 / p>

var fullName: String {
    return firstName + lastName
}

在这里,我们假设firstNamelastName已经是对象的属性。这个属性没有初始化的意义,因为它没有存储在任何地方。它是按需每次获取的。这就是为什么没有意义做以下事情:

var dogName : String {
    return "Buster"
}

这对存储的属性没有任何好处,除了在存储String“Buster”时不会使用任何内存。

实际上,这是计算属性的简化版本。您会注意到Swift语言指南描述了计算属性中getset的使用。 set允许您在设置计算变量时更新其他变量的状态。例如:

var stored: Int

var computed: Int {

    get {
        return stored + 5
    }

    set {
        stored = newValue - 5
    }

}

Rajan的回答指出了一些有用的应用,例如从widthheightdepth获取和设置音量。

只读计算var只是一个计算的var,它只指定一个getter,在这种情况下,get关键字和括号不是必需的。

只读访问控制

在开发框架等模块时,通常只需要在该对象或框架内修改变量并使其对公众只读即可。

private var modifiableItem: String

public var item: String {
    return modifiableItem
}

这里的想法是modifiableItem只能在定义它的对象中变化。 private关键字确保它只能在创建它的对象的范围内访问,并使其成为var,以确保它可以被修改。那么,public var item是一个向公众公开的计算变量,使任何人都可以阅读,但不能改变变量。

正如Hamish在评论中指出的那样,使用private(set)更简洁地表达了这一点:

public private(set) var item: String

这可能是最好的解决方法,但前面的代码(使用私有存储属性和公共计算属性)证明了这种效果。

答案 1 :(得分:3)

let dogName = "Buster"

表示dogName变量一旦被分配"Buster"后就无法更改,并且变为常量

var dogName : String {
 return "Buster"
}

它是一个计算只读属性,您可以在其中进行一些计算,因为它是一个var,但是以下面定义的方式进行更改:

可以像

一样更改计算属性
var dogName : String {
     return "Stress"+"Buster"
}

从Apple Docs

中考虑此示例
struct Cuboid {
    var width = 0.0, height = 0.0, depth = 0.0
    var volume: Double {
        return width * height * depth
    }
}
let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")

会打印

// Prints "the volume of fourByFiveByTwo is 40.0"

这里,在初始化struct Cuboid的对象时计算卷,并在运行时计算。如果它被释放,那么你必须先使用一些常量来初始化它。

如果您想了解更多相关信息,请阅读计算属性部分here

答案 2 :(得分:1)

类/结构中的只读属性意味着您无法更改类/结构的该实例的属性值。它阻止我做:

someObject.dogName = "Buddy" // This fails - read-only property

但是,我仍然可以这样做:

var someVariable = someObject.dogName // someVariable now is "Buster"
someVariable = "Buddy" // This is OK, it's now "Buddy"

let常量意味着您不会在该代码块中更改该特定常量的值。

let someName = "Buster"
someName = "Buddy" // This fails - someName is a constant

答案 3 :(得分:1)

在你的例子中,他们是做同样事情的两种方式。但是,您可以使用计算属性执行更多操作。例如:

var dogName: String {
  return firstName + " " + lastName
}

此处,firstNamelastName在初始化时可能不知道。对于简单的let属性,这是不可能的。

您可能会将计算属性视为没有参数的方法。

答案 4 :(得分:0)

有两种不同的情况:

1)值类型:

struct DogValueType {

    var name: String

}

let dog1 = DogValueType(name: "Buster")

var dog2: DogValueType {
    return DogValueType(name: "Buster")
}

let dog3: DogValueType = {
    return DogValueType(name: "Buster")
}()
  • dog1 - dog3无法更改或变异
  • dog1& dog3存储值
  • 每次访问时,
  • dog3都会计算值

2)参考类型:

class DogReferenceType {

    var name: String

    init(name: String) {
        self.name = name
    }
}

let dog4 = DogReferenceType(name: "Buster")

var dog5: DogReferenceType {
    return DogReferenceType(name: "Buster")
}

let dog6: DogReferenceType = {
    return DogReferenceType(name: "Buster")
}()
  • dog4 - dog6无法更改,但可以进行变异
  • dog4& dog6存储对象的引用。
  • dog5每次访问时都会创建对象