swift的结构体和类之下标和继承

Subscripts(下标)

类、结构体和枚举类型都可以定义下标作为访问诸如集合、列表、序列元素的快捷方式。在没有单独的设定和读取元素数值的方法的情况下,可以利用下标实现元素的设定和读取。例如,Array实例访问元素的方式someArray[index]和字典实例的访问元素方式someDictionary[key]。

对于一个类型,开发者可以定义多种下标形式,类似于函数的重载,具体抵用哪种方式由传入的参数决定。

下标语法(Subscripts Syntax)

Subscripts enables you to query instances of a type by writing one or more values in squre brackets after the instance name.

struct SomeStruct {
    //read-write
    subscript(index : Int) -> Int {
        get {
            return index * index
        }
        set {
            //perform a suitable setting action here
        }
    }
    //read-only
    subscript( key : String) -> Int {
        return 0
    }
}

struct TimeTable {
    let multiplier : Int
    subscript(index : Int) -> Int {
        return multiplier * index
    }
}

let threeTimesTable = TimeTable(multiplier: 3)
print("six times three is \(threeTimesTable[6])")

Subscripts Usage(下标用法)

下标额最具代表性用法是作为访问集合、列表、序列的元素的快捷方式。对于自定义的类或者结构体,开发者可以左右的发挥趋势线下标的用法。

var numberOfLegs = ["spider" : 8,"ant" : 6, "cat" : 4]
numberOfLegs["birds"] = 2

Subcripts Options

下标允许任意类型的数据作为参数,也允许返回任意类型的数据,甚至可以使用可变参数,但是不能使用in-out类型的参数或者默认参数(提供默认值)。开发者可以提供、多种下标的实现,具体使用哪个实现由下标使用时方括号内传入的参数确定。这个机制称作下标重载(Subscripts Overloading)。

struct Martrix {
    let rows : Int
    let cloumns: Int
    var grid : [Double]
    init(rows: Int, cloumns : Int) {
        self.rows = rows
        self.cloumns = cloumns
        grid = Array(repeating: 0.0, count: rows * cloumns)
    }

    func indexIsValid(row : Int, cloumn : Int) -> Bool {
        return row >= 0 && row < rows && cloumn >= 0 && cloumn < cloumns
    }

    subscript(row : Int,cloumn: Int) -> Double {
        get {
            assert(indexIsValid(row: row, cloumn: cloumn)," Index out of range")
            return grid[(row * cloumns) + cloumn]
        }
        set {
            assert(indexIsValid(row: row, cloumn: cloumn)," Index out of range")
            grid[(row * cloumns) + cloumn] = newValue
        }
    }
}

func testScripts(){
    var martrix = Martrix(rows: 2, cloumns: 2)
    print(martrix)
    martrix[0,1] = 1.5
    martrix[1,1] = 3.2
    print(martrix)
}
testScripts()

运行结果:

Martrix(rows: 2, cloumns: 2, grid: [0.0, 0.0, 0.0, 0.0])
Martrix(rows: 2, cloumns: 2, grid: [0.0, 1.5, 0.0, 3.2])

Inheritance(继承)

subclass && superClass

swift中,子类可以调用或者访问父类的方法、属性和下标,或者提供自己的实现(称作override)重新定义或者改变父类默认的行为。子类可以给父类的任意属性(包括存储属性和计算属性)添加属性观察者来监控父类属性值的变化。

Define a Base Class and Subclassing

Any Class that does not inherit from another class is known as base class. Sunclassing is the act of basing a new class on an existing class. The subclass inherits characteristic from the existing class, which you can then refine or modify. You can also add new characteristic to the sub class.

class Vehicle {
    var currentSpeed = 0.0
    var description : String {
        return "Traveling in \(currentSpeed ) miles per hour"
    }
    func makeNoise()  {
        print("vehicle is making noise!")
    }
}
class Bicycle : Vehicle {
    var hasBasket = false
}

重写(Override)

对于父类的方法和属性以及下标,子类可以提供适合自己的个性化个性化的实现,称作重写。语法:用关键词override修饰方法或者属性的名字。

访问父类的属性,调用父类的方法,使用父类的下标

  1. 重写的方法someMethod()在自己的实现中可以通过super.someMethod()调用父类的someMethod()方法。
  2. 重写的属性someProperty在自己的getter和setter实现中可以通过super.someProperty访问父类的someProperty属性。
  3. 重写的下标someIndex可以在自己的实现中通过super[someIndex]使用父类的下标。

重写方法

class Vehicle {
    var currentSpeed = 0.0
    var description : String {
        return "Traveling in \(currentSpeed ) miles per hour"
    }
    func makeNoise()  {
        print("vehicle is making noise!")
    }
}
class Bicycle : Vehicle {
    var hasBasket = false
    override func makeNoise() {
        print("bicycle is making noise!")
    }

}

重写属性

重写属性的getter和setter

需要注意:

  1. 继承的read-only属性可以重写为read-write属性,具体做法:重写时提供getter和setter函数;但是read-write属性不能被重写为read-only属性。
  2. 重写的时候,可以只提供getter函数,也可以setter和getter函数一起提供;不能只提供setter函数。
class Vehicle {
    var currentSpeed = 0.0 {
    }
    var description : String {
        return "Traveling in \(currentSpeed ) miles per hour"
    }
    func makeNoise()  {
        print("vehicle is making noise!")
    }
}

class Car : Vehicle {
    var gear = 1
    var newDescription : String = ""
    override var description: String {
        get {
            return super.description + " in gear \(gear)"
        }
        set {
            newDescription = newValue
        }
    }
}
let car = Car()
car.currentSpeed = 25.0
car.gear = 3
print("car : \(car.description)")

运行结果:

car : Traveling in 25.0 miles per hour in gear 3.

重写属性观察者

开发者可以对继承来的属性添加属性观察者,这个机制使得开发者能在这些属性值的变化的时候及时获得通知。

class Vehicle {
    var currentSpeed = 10.0
    var description : String {
        return "Traveling in \(currentSpeed ) miles per hour"
    }
    func makeNoise()  {
        print("vehicle is making noise!")
    }
}
class Car : Vehicle {
    var gear = 1
    var newDescription : String = ""
    override var description: String {
            return super.description + " in gear \(gear)"
    }
}

class AutomaticCar : Car {
    override var currentSpeed: Double {
        willSet {
            print("Before speed changes, in gear = \(Int(self.currentSpeed / 5.0) + 1).")
        }
        didSet {
            gear = Int(self.currentSpeed / 5.0) + 1
            print("After speed changes, in gear \(gear).")
        }
    }
}

let automaticCar = AutomaticCar()
automaticCar.currentSpeed = 35.0

运行结果:

Before speed changes, in gear = 3.
After speed changes, in gear 8.

注意:

  1. 不能给继承的常量存储属性和只读(read-only)的计算属性添加观察者,因为这些属性的值压根不会发生改变。
  2. 同一个属性不能同时重载setter和观察者,因为在setter函数里面也可以及时监测到属性值的变化。

防止重写(Preventing Overrides)

用final标记的属性、方法和下标,可以禁止他们被子类重写,例如 final var,final let, final func,final class func 和 final subscripts. 如果尝试重写,会触发compile-time error。扩展中定义的方法、属性和下标也可以用final修饰。如果开发者用final修饰整个类形如final class,那么这个类就不能被继承,如果尝试继承会导致触发compile-time error。

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

推荐阅读更多精彩内容