=========================

重写实例属性

我们可以在子类中重写从父类继承来的属性,属性有实例属性和静态属性之分,他们在具体实现也是不同的。

实例属性的重写一方面可以重写getter和setter访问器,另一方面可以重写属性观察者。

计算静态属性需要使用getter和setter访问器,而存储属性不需要。子类在继承父类后,也可以通过getter和setter访问器重写父类的存储属性和计算属性。

下面看一个示例:

  1. class Person {
  2. var name: String        //存储属性
  3. var age: Int            //存储属性
  4. func description() -> String {
  5. return "\(name) 年龄是: \(age)"
  6. }
  7. init (name: String, age: Int) {
  8. self.name = name
  9. self.age  = age
  10. }
  11. }
  12. class Student: Person {
  13. var school: String
  14. override var age: Int { //重写属性前面要添加override关键字
  15. get {
  16. return super.age
  17. }
  18. set {
  19. super.age = newValue < 8 ? 8: newValue
  20. }
  21. }
  22. convenience init() {
  23. self.init(name: "Tony", age: 18, school: "清华大学")
  24. }
  25. init (name: String, age: Int, school: String) {
  26. self.school = school
  27. super.init(name: name, age: age)
  28. }
  29. }
  30. let student1 = Student()
  31. print("学生年龄:\(student1.age)")
  32. student1.age = 6
  33. print("学生年龄:\(student1.age)")

从属性重写可见,子类本身并不存储数据,数据是存储在父类的存储属性中的。

以上示例是重写属性getter和setter访问器,我们还可以重写属性观察者,代码如下:

  1. class Person {
  2. var name: String
  3. var age: Int
  4. func description() -> String {
  5. return "\(name) 年龄是: \(age)"
  6. }
  7. init (name: String, age: Int) {
  8. self.name = name
  9. self.age  = age
  10. }
  11. }
  12. class Student: Person {
  13. var school: String
  14. override var age: Int {  //重写了age属性观察者
  15. willSet {              //如果只关注修改之前的调用,可以只重写willSet观察者
  16. print("学生年龄新值:\(newValue)")
  17. }
  18. didSet{                //如果只关注修改之后的调用,可以只重写didSet观察者
  19. print("学生年龄旧值:\(oldValue)")
  20. }
  21. }
  22. convenience init() {
  23. self.init(name: "Tony", age: 18, school: "清华大学")
  24. }
  25. init (name: String, age: Int, school: String) {
  26. self.school = school
  27. super.init(name: name, age: age)
  28. }
  29. }
  30. let student1 = Student()
  31. print("学生年龄:\(student1.age)")
  32. Student1.age = 6
  33. print("学生年龄:\(student1.age)")

代码Student1.age = 6修改了age属性,修改前后的输出结果如下:

学生年龄新值:6

学生年龄旧值:18

重写静态属性

在类中静态属性定义使用class或static关键字,但是使用哪一个要看子类中是否重写该属性。class修饰的属性可以被重写,static关键字就不能被重写。

示例代码如下:

  1. class Account {
  2. var amount: Double = 0.0                // 账户金额
  3. var owner: String = ""                   //账户名
  4. var interestRate: Double = 0.0668     //利率
  5. //class不能换成static
  6. class var staticProp: Double {              //静态属性staticProp
  7. return 0.0668 * 1_000_000
  8. }
  9. var instanceProp: Double {
  10. return self.interestRate * self.amount
  11. }
  12. }
  13. class TermAccount: Account {
  14. //class换成static
  15. override class var staticProp: Double {     //重写静态属性staticProp
  16. return 0.0700 * 1_000_000
  17. }
  18. }
  19. //访问静态属性
  20. print(Account.staticProp)
  21. print(TermAccount.staticProp)

由于要被重写所以代码class var staticProp: Double 中的class不能换成static。代码overrideclass var staticProp: Double中的静态属性staticProp可以使用class或static,除非在TermAccount的子类中重写属性staticProp。

================================

重写实例方法

在子类中重写从父类继承来的实例方法和静态方法。先介绍实例方法的重写。

下面看一个示例:

  1. class Person {
  2. var name: String
  3. var age: Int
  4. func description() -> String {    //实例方法
  5. return "\(name) 年龄是: \(age)"
  6. }
  7. class func printClass() ->() {    //静态方法
  8. print( "Person 打印...")
  9. }
  10. init (name: String, age: Int) {
  11. self.name = name
  12. self.age  = age
  13. }
  14. }
  15. class Student: Person {
  16. var school: String
  17. convenience init() {
  18. self.init(name: "Tony", age: 18, school: "清华大学")
  19. }
  20. init (name: String, age: Int, school: String) {
  21. self.school = school
  22. super.init(name: name, age: age)
  23. }
  24. override func description() -> String {   //重写实例方法description,重写的方法前面要添加关键字override
  25. print("父类打印 \(super.description())")
  26. return "\(name) 年龄是: \(age), 所在学校: \(school)。"
  27. }
  28. override class func printClass() ->() {   //重写静态方法printClass
  29. print( "Student 打印...")
  30. }
  31. }
  32. let student1 = student()
  33. print("学生1:\(student1.description())") //调用了description方法
  34. Person.printClass()
  35. Student.printClass()

使用super.description()语句调用父类的description方法,其中super指代父类实例。

重写静态方法printClass,在静态方法中不能访问实例属性。

调用了description方法。由于在子类中重写了该方法,所以调用的是子类中的description方法。输出结果是:

父类打印 Tony 年龄是: 18

学生1:Tony 年龄是: 18, 所在学校: 清华大学。

为了测试静态方法重写,调用Person.printClass()语言,它是调用父类的printClass静态方法,输出结果是:

Person 打印...

调用Student.printClass()语言,它是调用子类的printClass静态方法,输出结果是:

Student 打印...

重写静态方法

与类的静态属性定义类似,静态方法使用class或static关键字,但是使用哪一个要看子类中是否重写该方法。class修饰的静态方法可以被重写,static关键字就不能被重写。

示例代码如下:

  1. class Account {
  2. var owner: String = "Tony"     //账户名
  3. //不能换成static
  4. class func interestBy(amount: Double) -> Double {         //静态方法
  5. return 0.08886 * amount
  6. }
  7. }
  8. class TermAccount: Account {//定期账户
  9. //可以换成static
  10. override class func interestBy(amount: Double) -> Double {    //静态方法
  11. return 0.09 * amount
  12. }
  13. }
  14. //调用静态方法
  15. print(Account.interestBy(10_000.00 ))
  16. print(TermAccount.interestBy(10_000.00 ))

由于被重写所以代码class funcinterestBy(amount: Double) -> Double中的class不能换成static。静态方法interestBy可以使用class或static,除非在TermAccount的子类中重写方法interestBy。

==============================================

下标是一种特殊属性。子类属性重写是重写属性的getter和setter访问器,对下标的重写也是重写下标的getter和setter访问器。

下面看一个示例:

  1. class DoubleDimensionalArray {
  2. let rows: Int, columns: Int
  3. var grid: [Int]
  4. init(rows: Int, columns: Int) {
  5. self.rows = rows
  6. self.columns = columns
  7. grid = Array(count: rows * columns, repeatedValue: 0)
  8. }
  9. subscript(row: Int, col: Int) -> Int {    //定义下标
  10. get {
  11. return grid[(row * columns) + col]
  12. }
  13. set {
  14. grid[(row * columns) + col] = newValue
  15. }
  16. }                     //定义下标
  17. }
  18. class SquareMatrix: DoubleDimensionalArray {
  19. override subscript(row: Int, col: Int) -> Int {   //重写父类下标
  20. get {
  21. return super.grid[(row * columns) + col]
  22. }
  23. set {
  24. super.grid[(row * columns) + col] = newValue * newValue
  25. }
  26. }
  27. }
  28. var ary2 = SquareMatrix(rows: 5, columns: 5)
  29. for var i = 0; i < 5; i++ {
  30. for var j = 0; j < 5; j++ {
  31. ary2[i,j] = i + j
  32. }
  33. }
  34. for var i = 0; i < 5; i++ {
  35. for var j = 0; j < 5; j++ {
  36. print("\t\t \(ary2[i,j])")
  37. }
  38. print("\n")
  39. }

其中super.grid[(row * columns) + col]语句中使用super调用父类的grid属性。

其中super.grid[(row * columns) + col] = newValue * newValue语句是给父类的grid属性赋值。

Swift—重写-备的更多相关文章

  1. Swift - 重写UIKit框架类的init初始化方法(以UITabBarController为例)

    原来写了篇文章讲UITabBarController的用法,当时是从UIViewController跳转到UITabBarController页面,代码如下: 1 self.presentViewCo ...

  2. 用Swift重写公司OC项目(Day1)--程序的AppIcon与LaunchImage如何设置

    公司之前的APP呢经过了两次重写,都是使用OC由本人独立开发的,不过这些东西我都不好意思说是自己写的,真心的一个字:丑!!! 客观原因来说主要是公司要的特别急,而且注重的是功能而非效果,公司的美工之前 ...

  3. Swift—静态方法-备

    静态方法与静态属性类似,Swift中定义了静态方法,也称为类型方法.静态方法的定义与静态属性类似,枚举和结构体的静态方法使用的关键字是static:类静态方法使用的关键字是class或static,如 ...

  4. Uber使用Swift重写APP的踩坑经历及解决方案(转载)

    本文出自Uber移动架构和框架组负责人托马斯·阿特曼于2016年在湾区Swift峰会上的演讲,分享了使用Swfit重写Uber的好与坏.以下为译文: 我是托马斯·阿特曼,目前是Uber移动架构和框架组 ...

  5. 用Swift重写公司OC项目(Day2)--创建OC与Swift的桥接文件,进而调用OC类库

    昨天把项目中的图标以及启动转场图片弄好了,那么今天,我们可以开始慢慢进入到程序的编写当中了. 由于swift较新,所以类库还不够完善,但是不用担心,苹果早就出了解决方案,那就是使用桥接文件,通过桥接文 ...

  6. Swift—析构函数-备

    与构造过程相反,实例最后释放的时候,需要清除一些资源,这个过程就是析构过程.在析构过程中也会调用一种特殊的方法deinit,称为析构函数.析构函数deinit没有返回值,也没有参数,也不需要参数的小括 ...

  7. Swift—下标-备

    看下面的示例代码是不是使用过: var studentList: String[]  = ["张三","李四","王五"] studentL ...

  8. swift闭包-备

    我给Swift 中的闭包一个定义:闭包是自包含的匿名函数代码块,可以作为表达式.函数参数和函数返回值,闭包表达式的运算结果是一种函数类型. Swift中的闭包类似于Objective-C中的代码块.J ...

  9. Swift重写UIButton的图片和标题的位置

    import UIKit class ResetBtn: UIButton { let IMAGE_RATIO :CGFloat = 0.7 // 图片占整个按钮高度的比例 let TITLE_FON ...

随机推荐

  1. 未能找到类型或命名空间名称“XXXX”(是否缺少 using 指令或程序集引用?) 转

    未能找到类型或命名空间名称“XXXX”(是否缺少 using 指令或程序集引用?)   项目中 App_Code 文件夹中的类的命名空间,在添加的页面的  using XXXX  时,提示 未能找到类 ...

  2. Minimum Path Sum——LeetCode

    Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which ...

  3. Column count of mysql.proc is wrong. Expected 20, found 16. Created with MySQL 50096, now running 50173.

    IDEA链接mysql提示 Column count of mysql.proc is wrong. Expected 20, found 16. Created with MySQL 50096, ...

  4. windows 编程—— 使用函数笔记

    目录: 创建滚动条 滚动条函数(新老版本) 取得设备内容句柄hdc 设置 hdc 中的属性 画点画线 画填充图形 使用自定义的 画笔 和 画刷 矩形.区域和剪裁 关于GDI映像模式 其他常用的方便计算 ...

  5. jQuery(二)

    jQuery学完了!好用! 1.用定时器做的jquery里面的animate效果 <!DOCTYPE html> <html lang="en"> < ...

  6. nagios 实现Mysql 主从同步状态的监控

    一.系统环境 主机名 IP nagios 192.168.15.111 mysql_s 192.168.15.21 二.操作步骤 2.1 mysql_s端的配置 2.1.1 编写check_mysql ...

  7. 标C编程笔记day06 动态分配内存、函数指针、可变长度參数

    动态分配内存:头文件 stdlib.h     malloc:分配内存     calloc:分配内存,并清零     realloc:调整已分配的内存块大小     演示样例:         in ...

  8. [Angular + Webpack] ocLazyLoad compoment

    $stateProvider .state('landing', { url: '/', views: { 'body@': { template: '<olr-landing></ ...

  9. js禁止浏览器滚屏方法

    在有些需求中需要对页面进行限制页面的查看权限,阻止用户滚动浏览器.那么我们就要禁止鼠标的滚动事件,并且如果浏览器的滚动事件一旦触发我们就将滚动条重置为0就可以了.以下是具体代码: //出现滚动值立马归 ...

  10. Java基础知识强化20:面向对象和面向过程的思想对比

    面向对象与面向过程的区别  1. 与面向对象编程思想相比较的,往往是面向过程的编程思想,其实在我来理解,两者并不冲突,原因是面向对象的编程也必须使用面向过程的思维来实现具体的功能,所以我认为,两者的区 ...