繁体   English   中英

Swift 中的属性和变量有什​​么区别?

[英]What is the difference between a property and a variable in Swift?

从一些初始教程中,我看到属性属于一个类,并且本质上是 C++ 世界中使用的“全局变量”(在几年前编码)。 我还将变量更多地视为仅在方法中使用/存储信息的“本地”实体。

然后我遇到了这个 Quora 线程: https ://www.quora.com/Apple-Swift-programming-language/What-is-the-difference-between-a-property-and-a-variable 现在我看到属性是能够执行与其调用相关的代码。 这很酷,但也为我打开了一大堆其他问题。

还有其他简单明了的方法来记住属性和变量之间的区别吗?

属性属于对象,而变量不属于。 可以声明变量而不必与特定类或其他对象相关联。 属性必须与特定对象关联(即:类、枚举或结构)

局部变量只是您使用的东西。 您可以完全控制这些,如果您更改函数中的变量,则函数之外的任何内容都不会知道。 如果我编写了一个框架并且你使用它,并且我决定更改函数的局部变量,那么使用我的框架的你的应用程序将继续工作,就像没有任何改变一样。

另一方面,类描述了一个契约。 当您使用课程时,您可以访问他们公开宣传的所有内容。 这意味着,如果我编写了一个框架并且您使用它,如果我更改或删除了一个类的公共成员,那么如果您之前使用该成员,您的代码将会中断。

出于这个原因,在许多语言中,将实例变量标记为公共是不好的做法。 没有附加逻辑的实例变量,如果我想在某个时候在字段更改时触发某些东西,或者如果我想完全删除该字段(而是在子对象或其他东西中报告一个值),那么我就卡住了更改公共合同(例如,在一对get / set方法中转换字段),并可能破坏您的代码。

出于这个原因,Swift 使属性成为间接的。 Swift 属性在大多数情况下可以被视为愚蠢的值,但是如果您需要从存储值更改为计算值或其他东西,您可以在不更改类接口的情况下进行操作。 这样,您就不会破坏依赖该属性的现有代码。

Swift 变量、常量、属性

[迅捷类型]

variable - 地址的命名存储。 每个变量都有一个定义内存大小、属性和行为的类型

Swift 变量和常量

constant是一个variable ,但定义后不能修改。

//definition
var <name> = <initial_value>
//type annotation
var <name>: <Swift_type> [= <initial_value>] // [] is optional

//var - variable
var myVariable1 = 11 
var myVariable2: Int 
myVariable2 = 12

//let - constant
let myConstant1 = 21 
let myConstant2: Int 
myConstant2 = 22

全局变量和局部变量

全局变量是在函数、类之外定义的变量。 局部变量是:类型 context(class, struct, enum) [About]内的变量,函数内,函数参数

财产

property - 将值与类型上下文相关联。 它是一个变量 + 有界getter/setter 它具有字段语法,但在底层使用方法(getter/setter)。

存储属性和计算属性

它们可以属于实例( instance property )或类型( type property ):
Stored property (类、结构)
Computed property (类、结构、枚举)

Stored property - 是一个local variable -> 类型上下文中的变量。 Swift 存储属性不支持像 Objective-C 这样的instance variable

  • 变量存储属性 - var
  • 常量存储属性 - let

它支持property observerswillSetdidSet

Computed property - 提供getter和可选的setter来每次计算一个值

public class Person {
    var firstName = "John"
    var lastName = "Wick"
    
    var fullNameComputedProperty: String {
        get {
            return "\(firstName) \(lastName)"
        }
        
        //optional
        set {
            let arr = newValue.split(separator: " ")
            firstName = String(arr[0])
            lastName = String(arr[1])
        }
    }
    
    var addressStoredProperty: String {
        //Property Observers
        willSet {
            print("old address:\(addressStoredProperty)")
            print("new address:\(newValue)")
            //addressStoredProperty is not updated yet
        }
        didSet {
            print("old address:\(oldValue)")
            print("new address:\(addressStoredProperty)")
        }
    }
}

懒惰的存储属性

属性是在首次访问时计算的(按需)

  • 只有var lazy因为let在初始化期间必须有一个值

通过闭包初始化/自定义存储属性

官方文档

您可以在closure的帮助下初始化/设置/自定义存储的属性

  • 最后的()立即执行闭包并为存储的属性赋值(计算并返回一个值)。
  • 在初始化的情况下,不可能访问任何实例变量或函数,因为它尚未初始化
  • 在初始化的情况下,它只会为每个对象执行一次,或者如果你使用静态 - 一次用于类[示例]

例子

func testStoredPropertyWithClosure() {
    class ClassA { }
    
    class ClassB {
        static let staticStoredProperty: ClassA = {
            //is called only when you access to it like ClassB.staticStoredProperty
            print("init staticStoredProperty")
            return ClassA()
        }()
        
        var storedProperty: ClassA = {
            print("init storedProperty")
            //self.foo() //Error: Class declaration cannot close over value 'self' defined in outer scope
            return ClassA()
        }()
        
        func foo () {
            storedProperty = {
                print("customize storedProperty")
                return ClassA()
            }()
        }
    }
    
    let b = ClassB()
    b.foo()
    
    ClassB.staticStoredProperty
}

closure stored propertyComputed property

  • closure stored property被调用一次,可以在初始化后更改(如果是var
  • Computed property在每次调用时计算

[Java 变量、属性...]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM