Day10 属性 (Properties)、方法(Methods)

本页包含内容:
• 存储属性
• 计算属性
• 属性观察器
• 类型属性

    >• 实例方法
    • 类型方法

一:属性###

1、存储属性
简单来说,一个存储属性就是存储在特定类或结构体实例里的一个常量或变量。存储属性可以是变量存储属性(用关键字 var 定义),也可以是常量存储属性(用关键字 let 定义)。可以在定义存储属性的时候指定默认值。

    //下面的例子定义了一个名为 FixedLengthRange 的结构体,该结构体用于描述整数的范围,且这个范围值在被创建后不能被修改.
    struct FixedLengthRange {
        var firstValue : Int
        let length : Int
    }
    var  rangeOfThreeItems = FixedLengthRange.init(firstValue: 0, length: 3)
    // 该区间表示整数0,1,2
    rangeOfThreeItems.firstValue = 6
    // 该区间现在表示整数6,7,8
  • 常量结构体的存储属性

// 如果创建了一个结构体的实例并将其赋值给一个常量,则无法修改该实例的任何属性,即使有属性被声明为变量也不行:

    let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
    // 该区间表示整数0,1,2,3
  rangeOfFourItems.firstValue = 6
    // 尽管 firstValue 是个变量属性,这里还是会报错

这种行为是由于结构体(struct)属于值类型。当值类型的实例被声明为常量的时候,它的所有属性也就成了常量。
属于引用类型的类(class)则不一样。把一个引用类型的实例赋给一个常量后,仍然可以修改该实例的变量属性。

  • 延迟存储属性
    延迟存储属性是指当第一次被调用的时候才会计算其初始值的属性。在属性声明前使用 lazy 来标示一个延迟存储属性。

注意:
必须将延迟存储属性声明成变量(使用 var 关键字),因为属性的初始值可能在实例构造完成之后才会得到。
而常量属性在构造过程完成之前必须要有初始值,因此无法声明成延迟属性。

下面的例子使用了延迟存储属性来避免复杂类中不必要的初始化。例子中定义了 DataImporter 和 DataManager 两个类,下面是部分代码:

    class DataImporter {
        /*
         DataImporter 是一个负责将外部文件中的数据导入的类。 这个类的初始化会消耗不少时间。
         */
        var fileName = "data.txt"
        // 这里会提供数据导入功能
    }
    
    class DataManger {
        lazy var importer = DataImporter()
        var data = [String]()
    }
    let manager = DataManger()
    manager.data.append("Some data")
    manager.data.append("Some more data")
    // DataImporter 实例的 importer 属性还没有被创建

由于使用了 lazy ,importer 属性只有在第一次被访问的时候才被创建。比如访问它的属性 fileName 时:

    print(manager.importer.fileName)
    // DataImporter 实例的 importer 属性现在被创建了
    // 输出 "data.txt”

2、计算属性

    struct Point {
        var x = 0.0, y = 0.0
    }
    struct Size {
        var width = 0.0, height = 0.0
    }
    
    struct Rect {
        var origin = Point()
        var size = Size()
        var center: Point {
            get {
                let centerX = origin.x + (size.width / 2)
                let centerY = origin.y + (size.height / 2)
                return Point(x: centerX, y: centerY)
            }
            set(newCenter) {
                origin.x = newCenter.x - (size.width / 2)
                origin.y = newCenter.y - (size.height / 2)
            }
        } }
    var square = Rect(origin: Point(x: 0.0, y: 0.0),size: Size(width: 10.0, height: 10.0))
    let initialSquareCenter = square.center
    square.center = Point(x: 15.0, y: 15.0)
    print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
    // 打印 "square.origin is now at (10.0, 10.0)”
  • 只读计算属性

只有 getter 没有 setter 的计算属性就是只读计算属性。只读计算属性总是返回一个值,可以通过点运算符访问,但不能设置新的值。
只读计算属性的声明可以去掉get关键字和花括号:

<pre>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)")</pre>

** 3、属性观察器**
• 在新的值被设置之前调用
• 在新的值被设置之后立即调用

    class SomeClass {
        static var storedTypeProperty = "Some value."
        static var computedTypeProperty: Int {
            return 27 }
        class var overrideableComputedTypeProperty: Int {
            return 107
        }

** 4、类型属性语法**
使用关键字 static 来定义类型属性。在为类定义计算型类型属性时,可以改用关键字 class 来支持子类对父类的实现进行重写。
下面的例子演示了存储型和计算型类型属性的语法:

        struct SomeStructure {
            static var storedTypeProperty = "Some value."
            static var computedTypeProperty: Int {
                return 1
            }
        }
        
        enum SomeEnumeration {
            static var storedTypeProperty = "Some value."
            static var computedTypeProperty: Int {
                return 6
            }
        }
        
        class SomeClass {
            static var storedTypeProperty = "Some value."
            static var computedTypeProperty: Int {
                return 27
            }
            class var overrideableComputedTypeProperty: Int {
                return 107
            }
        }

二:方法(Methods)###

方法是与某些特定类型相关联的函数。类、结构体、枚举都可以定义实例方法;实例方法为给定类型的实例封装了具体的任务与功能。
类、结构体、枚举也可以定义类型方法;类型方法与类型本身相关联。

类型方法与 Objective-C 中的类方法(class methods)相似。结构体和枚举能够定义方法是 Swift 与 C/Objective-C 的主要区别之一。
在 Objective-C 中,类是唯一能定义方法的类型。但在 Swift 中,你不仅能选择是否要定义一个类/结构体/枚举,还能灵活地在你创建的类型(类/ 结构体/枚举)上定义方法。

** 1、实例方法 (Instance Methods)(-方法)**
实例方法是属于某个特定类、结构体或者枚举类型实例的方法。实例方法提供访问和修改实例属性的方法或提供与实例目的相关的功能,并以此来支撑实例的功能

实例方法要写在它所属的类型的前后大括号之间。实例方法能够隐式访问它所属类型的所有的其他实例方法和属性。
实例方法只能被它所属的类的某个特定实例调用。实例方法不能脱离于现存的实例而被调用。
下面的例子,定义一个很简单的 Counter 类, Counter 能被用来对一个动作发生的次数进行计数:

    class Counter {
        var count = 0
        func increment () {
            count += 1
        }
        func increment(by amount: Int) {
            count += amount
        }
        
        func reset() {
            count = 0
        }
    }
    //  Counter 类定义了三个实例方法:
    //   - increment 让计数器按一递增;
    //   - increment(by: Int) 让计数器按一个指 定的整数值递增;
    //   - reset 将计数器重置为0。
    
    let counter = Counter ()
    print(counter.count)
    //初始计数值是0
    counter.increment()
    print(counter.count)
    //计数值现在是1
    counter.increment(by: 5)
    print(counter.count)
    //计数值现在是6
    counter.reset()
    //计数值现在是0
    print(counter.count)

** 2、类型方法(+方法)**
实例方法是被某个类型的实例调用的方法。你也可以定义在类型本身上调用的方法,这种方法就叫做类型方法。
在方法的 func 关键字之前加上关键字 static ,来指定类型方法。
类还可以用关键字 class 来允许子类重写父类的方法实现。

    class SomeClasses {
        class func someTypeMethod () {
            //实现类型方法
            
        }
        
        static func testMethod () -> String {
            return "testMethod"
        }
    }
    //调用类型方法
    SomeClasses.someTypeMethod()
    let msg = SomeClasses.testMethod()
    print(msg)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,294评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,780评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,001评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,593评论 1 289
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,687评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,679评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,667评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,426评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,872评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,180评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,346评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,019评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,658评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,268评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,495评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,275评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,207评论 2 352

推荐阅读更多精彩内容