📜  Swift – 属性及其不同类型

📅  最后修改于: 2022-05-13 01:55:33.301000             🧑  作者: Mango

Swift – 属性及其不同类型

在 Swift 中,属性是存储在类实例中的关联值。或者我们可以说属性是与结构、类或枚举相关联的值。有两种属性:存储属性和计算属性。存储属性是存储在类实例中的属性。存储属性存储常量和变量值。计算属性用于为存储的属性创建自定义 get 和 set 方法。计算属性由类、结构和枚举提供,以提供属性的自定义行为。存储和计算属性通常与特定类型相关联,但可以与任何类型相关联。这些属性称为类型属性。我们可以使用类型属性为特定类型的属性提供默认值。

存储属性

存储属性是其值作为特定类型实例的一部分存储的属性。存储的属性可以是变量或常量。我们可以使用 var 创建一个变量存储属性,并使用 let 创建一个常量存储属性。

1、对于可变存储属性:这里我们使用var来创建可变存储属性。假设我们有一个名为 Person 的结构,其中包含一个名为 String 类型名称的存储属性。所以我们创建了一个 Person 实例并为 name 属性赋值。 name 属性是一个存储属性,所以它存储在 Person 结构的实例中。

Swift
// Swift program for variable stored properties
 
// Creating structure
struct Person
{
 
    // Stored property
    var name: String
}
 
// Creating a Person instance
let person = Person(name: "Geek2Geeks")
 
// Prints "The person's name is Geek2Geeks"
print("The person's name is \(person.name)")


Swift
// Swift program for constant stored properties
 
// Structure
struct Employee
{
 
    // Constant stored property
    let age: Int
     
    // Constant stored property
    let name: String
}
 
// Creating an Employee instance
let employee = Employee(age: 30, name: "Geek2Geeks")
 
// Prints "The employee's name is Geek2Geeks"
print("The employee's name is \(employee.name)")
 
// Prints "The employee's age is 30"
print("The employee's age is \(employee.age)")


Swift
// Swift program for lazy Property
 
// Class which contain lazy property
class GFG
{
    var Cname : String?
     
    // lazy property
    lazy var course : String = {[weak self] in
         
        guard let x = self else { return "Doesnot warp itself"}
        guard let y = x.Cname else { return "Course not found" }
         
        return "Course is: \(y)"
    }()
     
    init(Cname: String)
    {
        self.Cname = Cname
    }
}
 
// Assigning value
var y = GFG(Cname: "Swift")
 
// Displaying the result
print(y.course)


Swift
// Swift program for Computed Properties
 
// Structure
struct rectangle
{
    var len: Double
    var width: Double
     
    // Computed property
    var perimeter: Double{
     
        // Getter
        get{
            return (2 * (len + width))
        }
         
        // Setter
        set(newperimeter)
        {
            len = (newperimeter - width)/2
        }
    }
}
 
var ob = rectangle(len: 10, width: 5)
 
// Accessing the property
print("Perimeter: ", ob.perimeter)
 
// Setting property with new value
ob.perimeter = 40
 
// Accessing the property
print("Length: ", ob.len)


Swift
// Swift program for read-only computed property
 
// Structure to find the volume of Cuboid
struct CuboidVolume {
   
    var w = 0.0, h = 0.0, d = 0.0
     
    // Reao only computed property
    var Cvolume: Double {
       
        return w * h * d
    }
}
 
// Assigning values
let vol = CuboidVolume(w: 4.0, h: 4.0, d: 4.0)
 
// Accessing read only computed property
print("The volume is \(vol.Cvolume)")


Swift
// Swift program for property observers
 
// Class to count the total cat step
class Counter
{
    var totalCatSteps: Int = 0 {
     
        // Property observer
        willSet(newTotalCatSteps)
        {
            print("Setting cat totalSteps: \(newTotalCatSteps)")
        }
         
        // Property observer
        didSet {
            if totalCatSteps > oldValue  {
                print("Added new steps: \(totalCatSteps - oldValue)")
            }
        }
    }
}
 
// Creating class object
let CatStep = Counter()
 
// About to set CatStep to 105
// Added 105 steps
CatStep.totalCatSteps = 105
 
 
// About to set CatStep to 250
// Added 135 steps
CatStep.totalCatSteps = 240
 
// About to set CatStep to 370
// Added 130 steps
CatStep.totalCatSteps = 370


Swift
// Swift program for type property
 
// Ios is a type
struct Ios
{
 
    // Version is a type property
    static var version = "iOS 10"
     
    // getVersion is a type method
    static func getVersion()
    {
     
        // Printing the version
        print(version)
    }
}
 
// Printing the version
Ios.getVersion()
 
// Printing the version
print(Ios.version)


Swift
// Swift program to Querying and Setting Type Properties
 
// Ios is a type
struct Ios
{
    static var version = "iOS 10"
     
    // Version is a type property
    static var apilevel: Int{
        return 10
    }
}
 
// Querying
// Printing the version
print(Ios.version)
 
// Setting
// Setting the version
Ios.version = "iOS 11"
 
// Printing the version
print(Ios.version)
 
// Printing the apilevel
print(Ios.apilevel)


Swift
// Swift program to demonstrate the use of global and local variable
 
// Creating global variable
var globalVariable = "This is Global Variable"
 
func geeksforgeeks()
{
 
    // Creating local variable
    var localVariable = "This is Local Variable"
 
    print("Global Variable: \(globalVariable)")
    print("Local Variable: \(localVariable)")
}
 
// Calling the geeksforgeeks function
geeksforgeeks()
 
// Printing the global variable
print(globalVariable)


输出:

The person's name is Geek2Geeks

2.对于常量存储属性:这里我们使用let来创建一个常量存储属性。假设我们有另一个名为 Employee 的结构,它包含一个名为 age 的 Int 类型的常量存储属性。我们还创建了一个名为 String 类型名称的常量存储属性。

迅速

// Swift program for constant stored properties
 
// Structure
struct Employee
{
 
    // Constant stored property
    let age: Int
     
    // Constant stored property
    let name: String
}
 
// Creating an Employee instance
let employee = Employee(age: 30, name: "Geek2Geeks")
 
// Prints "The employee's name is Geek2Geeks"
print("The employee's name is \(employee.name)")
 
// Prints "The employee's age is 30"
print("The employee's age is \(employee.age)")

输出:

The employee's name is Geek2Geeks
The employee's age is 30

在这里,我们创建了一个常量 Employee 实例,并为 age 和 name 属性赋值。 age 属性是一个常量存储属性,因此它存储在 Employee 结构的实例中。 name 属性是一个常量存储属性,因此它存储在 Employee 结构的实例中。

惰性存储属性

延迟存储属性是一种将属性初始化推迟到第一次使用的方法。这对于昂贵的属性(例如 NSURL 对象)或大型集合(例如大型字典或数组)很有用。惰性属性对于创建初始值取决于另一个属性(例如当前日期或文件名)的属性也很有用。您可以通过在声明之前编写惰性修饰符来创建惰性属性。当属性的初始值需要复杂的设置时,它也很有用。

例子:

迅速

// Swift program for lazy Property
 
// Class which contain lazy property
class GFG
{
    var Cname : String?
     
    // lazy property
    lazy var course : String = {[weak self] in
         
        guard let x = self else { return "Doesnot warp itself"}
        guard let y = x.Cname else { return "Course not found" }
         
        return "Course is: \(y)"
    }()
     
    init(Cname: String)
    {
        self.Cname = Cname
    }
}
 
// Assigning value
var y = GFG(Cname: "Swift")
 
// Displaying the result
print(y.course)

输出:

Course is: Swift

说明:在上面的例子中,我们创建了一个名为 GFG 的类。此类包含一个名为 course 的惰性属性。此属性将返回一个包含课程名称的字符串。在这个属性中,我们使用weak self 来移除引用循环,并使用guard let 来进行可选的展开。

计算属性

计算属性由类、结构和枚举提供,以提供属性的自定义行为。它们类似于方法,但它们是作为类型本身的一部分而不是作为实例的一部分编写的。它们不存储值,而是使用 getter 和 setter 间接检索和设置属性及其值。计算属性可以分配给惰性 var 属性,而必须获取和设置的计算属性不能定义为常量 let。

例子:

迅速

// Swift program for Computed Properties
 
// Structure
struct rectangle
{
    var len: Double
    var width: Double
     
    // Computed property
    var perimeter: Double{
     
        // Getter
        get{
            return (2 * (len + width))
        }
         
        // Setter
        set(newperimeter)
        {
            len = (newperimeter - width)/2
        }
    }
}
 
var ob = rectangle(len: 10, width: 5)
 
// Accessing the property
print("Perimeter: ", ob.perimeter)
 
// Setting property with new value
ob.perimeter = 40
 
// Accessing the property
print("Length: ", ob.len)

输出:

Perimeter:  30.0
Length:  17.5

说明:上面的例子定义了一个称为矩形的结构,它包含一个名为 perimeter 的属性。周界是一个包含 getter 和 setter 的计算属性。在这个属性中,我们通过设置周长的值来找到矩形的周长和新的长度。

只读计算属性

只读计算属性是仅与 getter 一起存在的计算属性。它不包含二传手。此属性始终返回一个值,并且可以使用点语法访问。要声明只读计算属性,只需删除 get 关键字及其大括号。

例子:

迅速

// Swift program for read-only computed property
 
// Structure to find the volume of Cuboid
struct CuboidVolume {
   
    var w = 0.0, h = 0.0, d = 0.0
     
    // Reao only computed property
    var Cvolume: Double {
       
        return w * h * d
    }
}
 
// Assigning values
let vol = CuboidVolume(w: 4.0, h: 4.0, d: 4.0)
 
// Accessing read only computed property
print("The volume is \(vol.Cvolume)")

输出:

The volume is 64.0

说明:在这个例子中,我们有一个类 CuboidVolume,它有一个名为 Cvolume 的属性。此属性是只读计算属性。 Cvolume 属性只是一个 getter,没有 setter。 Cvolume 属性被定义为只读计算属性,因为它不需要存储值。它不需要存储在 CuboidVolume 结构的实例中,因为它只用于计算长方体的体积。

物业观察员

这些是在设置属性值时由系统自动调用的方法。在设置属性值后调用属性观察器,无论新值是否与属性的当前值不同。我们可以将属性观察器添加到任何存储或计算的属性,并观察该属性值的变化。对于存储的属性,当属性被分配一个新值时,观察者会被调用。对于计算属性,在读取或写入属性时调用观察者。我们可以使用 willSet 和 didSet 来观察属性值的变化。

例子:

迅速

// Swift program for property observers
 
// Class to count the total cat step
class Counter
{
    var totalCatSteps: Int = 0 {
     
        // Property observer
        willSet(newTotalCatSteps)
        {
            print("Setting cat totalSteps: \(newTotalCatSteps)")
        }
         
        // Property observer
        didSet {
            if totalCatSteps > oldValue  {
                print("Added new steps: \(totalCatSteps - oldValue)")
            }
        }
    }
}
 
// Creating class object
let CatStep = Counter()
 
// About to set CatStep to 105
// Added 105 steps
CatStep.totalCatSteps = 105
 
 
// About to set CatStep to 250
// Added 135 steps
CatStep.totalCatSteps = 240
 
// About to set CatStep to 370
// Added 130 steps
CatStep.totalCatSteps = 370

输出:

Setting cat totalSteps: 105
Added new steps: 105
Setting cat totalSteps: 240
Added new steps: 135
Setting cat totalSteps: 370
Added new steps: 130

解释:在上面的例子中,我们有一个包含 willSet 和 didSet 观察者的 Counter 类,当存储属性的值被设置时它们被调用。 willSet 观察者在值被存储之前被调用。在存储值之后调用 didSet 观察者。这里,willSet 观察者在值被存储之前打印一条消息,didSet 观察者在值被存储之后打印一条消息。如果新值大于属性的先前值,didSet 观察者会打印一条消息。

属性包装器

属性包装器是在另一个属性之上提供附加功能的属性。属性包装器是一个属性,它是它所包装的属性的子类。属性包装类是它包装的属性的子类。它为它包装的属性添加了额外的功能。或者换句话说,它在管理属性存储方式的代码和定义属性的代码之间添加了一个分离层。要使用属性包装器,我们必须在定义包装器时编写管理代码,然后我们可以通过对其应用多个属性来重用管理代码。

我们可以通过创建结构、枚举或定义 WrappedValue 属性的类来定义属性包装器。要将包装器应用于属性,只需在属性属性之前写入包装器的名称。

语法

在这里,Wrapper 是一个属性包装器,它包装了一个 T 类型的值。 Wrapper 类是它所包装的属性的子类。 Wrapper 类覆盖属性包装器的行为,例如通过覆盖属性包装器的设置器。

类型属性

每当我们创建一个类的新实例时,我们都可以设置该实例的属性。这些实例有它们自己的属性,这些被称为实例属性。所以如果我们想创建一个类的多个实例,我们可以单独设置每个实例的属性。但是单独设置每个实例的属性并不是一个好习惯。然后是类型属性来救援。类型属性在类的所有实例之间共享。只为我们创建的类型的所有实例创建属性的一个副本。

类型属性是使用 static 关键字创建的。所以我们可以使用类名来访问一个类型的属性。但是我们不能使用实例名称访问实例的属性。

句法:

在这里,我们创建了一个名为 typeProperty 的类型属性。 MyClass 类有一个名为 typeProperty 的静态属性。它可以有任何价值。 MyClass.typeProperty 是一个类型属性。它是一个共享财产。可以使用类名访问它。

例子:

迅速

// Swift program for type property
 
// Ios is a type
struct Ios
{
 
    // Version is a type property
    static var version = "iOS 10"
     
    // getVersion is a type method
    static func getVersion()
    {
     
        // Printing the version
        print(version)
    }
}
 
// Printing the version
Ios.getVersion()
 
// Printing the version
print(Ios.version)

输出:

iOS 10
   iOS 10

说明:我们有两个 iOs 对象。一个是使用 struct 关键字创建的,另一个是使用 class 关键字创建的。这是一个使用类型属性的简单示例。 Ios 结构有一个名为 version 的静态属性。它可以有任何价值。 ios.version 是一个类型属性。它是一个共享财产。静态函数getVersion() 是一个静态函数。它将使用类名调用。该函数的主体将只执行一次,并显示版本的值。我们使用类名 Ios 调用了 getVersion()函数。这是因为 getVersion()函数是一个静态函数。使用类名调用它。 print函数用于显示版本的值。

查询和设置类型属性

查询用于获取类型属性的值。该设置用于设置类型属性的值。使用类名查询和设置类型属性。我们可以使用点语法来查询和设置类型属性。

例子:

迅速

// Swift program to Querying and Setting Type Properties
 
// Ios is a type
struct Ios
{
    static var version = "iOS 10"
     
    // Version is a type property
    static var apilevel: Int{
        return 10
    }
}
 
// Querying
// Printing the version
print(Ios.version)
 
// Setting
// Setting the version
Ios.version = "iOS 11"
 
// Printing the version
print(Ios.version)
 
// Printing the apilevel
print(Ios.apilevel)

输出:

iOS 10
iOS 11
10

说明:这里我们正在创建一个名为 Ios 的结构。 Ios 有两种类型的属性。一种叫做版本。它可以有任何价值。另一个称为apilevel。它可以有任何价值。 apilevel 是一个计算属性。之所以计算它,是因为它取决于版本的值。我们正在使用类名 Ios 查询版本的值。 print函数用于显示版本的值。同样,我们也使用类名 Ios 设置版本的值。 print函数用于显示版本的值。

全局和局部变量

通常,变量是函数的局部变量。但也有一些例外。全局变量是在任何函数之外定义的变量。它们在整个程序中都可以访问。它们被称为全局变量。局部变量是在函数内部定义的那些变量。在 Swift 中,我们还可以声明计算变量。计算变量即时计算它们的值。这意味着每次访问时都会计算变量的值。它们被称为惰性变量。

例子:

迅速

// Swift program to demonstrate the use of global and local variable
 
// Creating global variable
var globalVariable = "This is Global Variable"
 
func geeksforgeeks()
{
 
    // Creating local variable
    var localVariable = "This is Local Variable"
 
    print("Global Variable: \(globalVariable)")
    print("Local Variable: \(localVariable)")
}
 
// Calling the geeksforgeeks function
geeksforgeeks()
 
// Printing the global variable
print(globalVariable)

输出:

Global Variable: This is Global Variable
Local Variable: This is Local Variable
This is Global Variable

说明:在这里,我们创建了一个名为 globalVariable 的全局变量。 globalVariable 是一个全局变量。它可以在整个程序中访问。局部变量称为局部变量。局部变量是局部变量。它只能在 geeksforgeeks函数内部访问。