iOS学习笔记43-Swift(三)类

一、Swift的类class

作为一门面向对象语言,类也是Swift的非常重要的类型,我们先来看下一个简单的类

//Swift中一个类可以不继承于任何其他基类,那么此类本身就是一个基类
class Person {
    //定义属性
    var name:String
    var height = 0.0
    //构造器方法,注意如果不编写构造方法默认会自动创建一个无参构造方法
    init(name:String){
        self.name = name
    }
    //析构器方法,在对象被释放时调用,类似于ObjC的dealloc,注意这里没有括号和参数,无法直接调用
    deinit{
        println("deinit...")
    }
    //定义对象方法
    func showMessage(){
        println("name=\(name),height=\(height)")
    }
}
//创建类的对象
var p = Person(name: "Liuting")
p.height = 170.0
p.showMessage() //结果:name=Liuting,height=170.0

//类是引用类型
var p2 = p
p2.name = "XiaoMing"
println(p.name) //结果:XiaoMing
//“===”表示等价于,这里不能使用等于“==”,等于用于比较值相等,p和p2是不同的值,但是指向的对象相同
if p === p2 {
    println("p===p2") //p等价于p2,表示二者指向同一个对象
}

二、属性

Swift中淡化了成员属性的概念,把属性分为两种:

1. 存储属性

无论从概念上还是定义方式上来看,存储属性更像其他语言中的成员变量,但是不同的是:

* 可以控制读写操作(var表示可读可写,let表示只读)

* 通过属性监视器来属性的变化(willSetdidSet

* 快速实现懒加载功能(lazy修饰)

2. 计算属性

计算属性并不直接存储一个值,而是提供getter来获取一个值,或者利用setter来间接设置其他属性。

下面是对象属性使用实例:
class Account {
    //定义存储属性,设置默认值,添加属性监听器
    var balance:Double = 0.0{
        //即将赋值时调用
        willSet{
            //注意此时修改balance的值没有用
            self.balance = 2.0
            //newValue表示即将赋值的新值,并且在属性监视器内部调用属性不会引起监视器循环调用
            println("Account.balance willSet,newValue=\(newValue),value=\(self.balance)")
        }
        //赋值完成后调用
        didSet{
            //注意此时修改balance的值将作为最终结果
            self.balance = 3.0
            //oldValue表示已经赋值的旧值,并且在属性监视器内部调用属性不会引起监视器循环调用
            println("Account.balance didSet,oldValue=\(oldValue),value=\(self.balance)")
        }
    }
}
class Person {
    //firstName、lastName、age是存储属性
    var firstName:String //var定义表示该存储属性可读可写
    var lastName:String
    let age:Int //let定义表示该存储属性只读

    //属性的懒加载,第一次访问才会初始化
    lazy var account = Account()//在Swift中懒加载的属性不一定就是对象类型,也可以是基本类型

    //fullName是一个计算属性,在get、set方法中不能直接访问计算属性,否则会引起循环调用
    var fullName:String{
        //获取该计算属性时调用
        get{
            return firstName + "." + lastName
        }
        //设置该计算属性时调用
        set{
            //set方法中的newValue表示即将赋值的新值,这里是分割字符串
            let array = split(newValue, maxSplit: Int.max,
                                allowEmptySlices: false,
                                     isSeparator: {$0=="."})
            if array.count == 2 {
                firstName = array[0]
                lastName = array[1]
            }
        }
    }
    //构造器方法,注意如果不编写构造方法默认会自动创建一个无参构造方法
    init(firstName:String, lastName:String, age:Int){
        self.firstName = firstName
        self.lastName = lastName
        self.age = age
    }
    //定义方法
    func showMessage(){
        println("name=\(self.fullName),age=\(self.age)")
    }
}
//创建对象
var p = Person(firstName: "Liu", lastName: "Ting", age:22)
p.showMessage() //结果:name=Liu.Ting,age=22
p.fullName = "Liu.HAHA" //设置计算属性
p.showMessage() //结果:name=Liu.HAHA,age=22

p.account.balance = 10
/* 下面是存储属性监听器方法打印:
Account.balance willSet,newValue=10,value=0.0
Account.balance didSet,oldValue=10,value=3.0
*/
println("p.account.balance=\(p.account.balance)") //结果:p.account.balance=3.0
  1. 计算属性并不直接存储一个值,而是提供getter来获取一个值,或者利用setter来间接设置其他属性;
  2. lazy属性必须有初始值,必须是变量不能是常量,因为常量在构造完成之前就已经确定了值;
  3. 在构造对象方法之前存储属性必须有值(可选类型除外),无论是变量属性还是常量属性,这个值既可以在属性创建时指定,也可以在构造方法内指定;
  4. 存储属性的默认值设置不会引起属性监视器的调用(另外在构造方法中赋值也不会引起属性监视器调用),只有在外部设置存储属性才会引起属性监视器调用;
除了上面的对象属性外,我们还可以定义类的属性:
class Student {
    //定义类的属性只需要在前面加static关键字即可,也是分为存储属性和计算属性,这里是计算属性
    static var skin:Array<String>{
        //只定义了getter,表示该计算属性是只读的
        get{
            return ["yellow", "white", "black"]
        }
    }
}
//读取类的属性
for color in Student.skin {
    println(color)
}

三、方法

Swift的类中的方法可分为以下几个类别:
  1. 构造器方法

    • 默认构造器方法(当存在有参数的指定构造器方法,被覆盖)
    • 指定构造器方法
    • 便利构造器方法
  2. 析构器方法
  3. 对象方法
  4. 类方法
以下是方法使用实例:
class Person {
    //定义属性
    var name:String
    var height:Double
    var age = 0
    //1.2.指定构造器方法,注意如果不编写构造方法,默认会自动创建一个无参构造方法
    init(name:String, height:Double, age:Int){
        self.name = name
        self.height = height
        self.age = age
    }
    //1.3.便利构造方法,通过调用指定构造方法、提供默认值来简化构造方法实现
    convenience init(name:String){
        self.init(name:name, height:0.0, age:0)
    }
    //2.析构方法,在对象被释放时调用,注意此方法没有括号,没有参数,无法直接调用
    deinit{
        println("deinit...")
    }
    //3.对象方法
    func modifyInfoWithAge(age:Int, height:Double){
        self.age = age
        self.height = height
    }
    //4.类方法,使用class修饰的方法即是类方法
    class func showClassName(){
        println("Class name is Person")
    }
}
//通过便利构造方法创建对象
var p = Person(name: "liuting")
//调用对象方法
p.modifyInfoWithAge(22,height: 170)
//调用类方法
Person.showClassName()
  1. 除构造方法、析构方法外,其他方法的参数默认除了第一个参数是局部参数,从第二个参数开始既是局部参数又是外部参数。但是,对于函数,默认情况下只有默认参数既是局部参数又是外部参数,其他参数都是局部参数。
  2. 构造方法的所有参数默认情况下既是外部参数又是局部参数
  3. 只有便利构造器方法才能调用当前类的指定构造方法
  4. 有参数的指定构造器方法会覆盖调用默认的无参构造器方法
  5. 一个对象被释放前,先自动调用自己的析构方法,然后一层一层往上调用父类的析构方法

四、下标脚本

下标脚本是一种访问集合的快捷方式,如果我们自定义的类具有集合类型的功能,我们可以定义下标脚本来快捷访问该类属性,定义下标脚本是通过关键字subscript进行的。

class Record {
    //定义属性,store是Record内部的存储结构,这里是字典
    var store:[String:String]
    //指定构造方法
    init(data:[String:String]){
        self.store = data
    }
    //下标脚本,下标索引为整形(注意也可以实现只有getter的只读下标脚本)
    subscript(index:Int) -> String{
        get{
            //字典的key进行排序后根据Index整形索引获取字典的值
            var key = sorted(Array(self.store.keys))[index]
            return self.store[key]!
        }
        set{
            //字典的key进行排序后根据Index整形索引设置字典的值
            var key = sorted(Array(self.store.keys))[index]
            self.store[key] = newValue //newValue和属性一样使用
        }
    }
    //下标脚本,下标索引为字符串
    subscript(key:String) -> String{
        get{
            return store[key]!
        }
        set{
            store[key] = newValue
        }
    }
}
//创建对象
var record = Record(data:["name":"liuting","sex":"male"])
println("r[0]=\(record[0])") //结果:r[0]=liuting
record["sex"] = "female"
println(record["sex"]) //结果:female

五、继承

和ObjC一样,Swift也是单继承的(可以实现多个协议,此时协议放在后面),子类可以调用父类的属性、方法,重写父类的方法,添加属性监视器,甚至可以将只读属性重写成读写属性。

//定义一个父类
class Person {
    var firstName:String
    var lastName:String
    var age:Int = 0
    var fullName:String{
        get{
            return firstName + " " + lastName
        }
    }
    //指定构造方法
    init(firstName:String,lastName:String){
        self.firstName = firstName
        self.lastName = lastName
    }
    //对象方法
    func showMessage(){
        println("name=\(self.fullName),age=\(self.age)")
    }
    //通过final声明,子类无法重写
    final func sayHello(){
        println("hello world.")
    }
}
//定义子类
class Student: Person {
    //重写属性,为属性添加监视器,重写都需要加override关键字
    override var firstName:String{
        willSet{
            println("firstName willSet")
        }
        didSet{
            println("firstName didSet")
        }
    }
    //添加子类属性
    var score:Double

    //子类指定构造方法一定要调用父类构造方法
    //并且必须在子类存储属性初始化之后调用父类构造方法
    init(firstName:String, lastName:String, score:Double){
        self.score = score
        super.init(firstName: firstName, lastName: lastName)
    }
    //便利构造方法
    convenience init(){
        self.init(firstName:"", lastName:"", score:0)
    }
    //将只读属性重写成了可写属性
    override var fullName:String{
        get{
            return super.fullName;
        }
        set{
            let array = split(newValue, maxSplit: Int.max,
                                allowEmptySlices: false,
                                     isSeparator: { $0 == "." })
            if array.count == 2 {
                firstName = array[0]
                lastName = array[1]
            }
        }
    }
    //重写对象方法
    override func showMessage() {
        println("name=\(self.fullName),age=\(self.age),score=\(self.score)")
    }

}
//创建子类对象
var p = Student()
p.firstName = "liu"
p.showMessage() //结果:name=liu,age=0,score=0
p.fullName = "Liu.Ting"
p.showMessage() //结果:name=Liu.Ting,age=0,score=0
p.sayHello()
  1. 只有指定构造方法才能调用父类的构造方法。
  2. 如果父类中存在有参数的指定构造方法,子类的指定构造方法不会自动调用父类无参的指定构造方法。
  3. 如果父类仅有一个无参构造方法(不管是否包含便利构造方法),子类的构造方法默认就会自动调用父类的无参构造方法(这种情况下可以不用手动调用)。
  4. 常量属性只能在定义它的类的构造方法中初始化,不能在子类中初始化
  5. 一个对象被释放前,先自动调用自己的析构方法,然后一层一层往上调用父类的析构方法。
  6. 便利构造方法必须调用同一个类中的其他指定构造方法(可以是指定构造方法或者便利构造方法),不能直接调用父类构造方法。

有什么问题可在下方评论区中提出!O(∩_∩)O哈!
时间: 2024-10-11 17:07:15

iOS学习笔记43-Swift(三)类的相关文章

iOS学习笔记14-网络(三)WebView

一.WebView WebView就是一个内嵌浏览器控件,在iOS中主要有两种WebView:UIWebView和WKWebView,UIWebView是iOS2之后开始使用,WKWebView是在iOS8开始使用,毫无疑问WKWebView将逐步取代笨重的UIWebView. WKWebView的优点: WKWebView更多的支持HTML5的特性 WKWebView更快,占用内存可能只有UIWebView的1/3 ~ 1/4 WKWebView高达60fps的滚动刷新率和丰富的内置手势 WK

【IOS学习笔记】Swift iOS 日期操作:NSDate、NSDateFormatter(转载)

转载自:http://blog.csdn.net/jinnchang/article/details/44592801 1.日期(NSDate) [objc] view plaincopy // 1.初始化 // 初始化一个当前时刻对象 var now = NSDate() // 初始化一个明天当前时刻对象 var tomorrow = NSDate(timeIntervalSinceNow: 24*60*60) // 初始化一个昨天当前时刻对象 var yestoday = NSDate(ti

iOS: 学习笔记, Swift与Objective-C混用简明教程(转载)

Swift与Objective-C混用简明教程 转载自:https://github.com/lifedim/SwiftCasts/tree/master/000_mix_swift_objc 我想很多iOS开发者在知道Swift后,心中最大的问题就是如何将Swift应用到原有项目之中.下面我将简要介绍这2种语言的混用方法,内容参考自官方文档 Using Swift with Cocoa and Objective-C ,推荐大家阅读. 在Swift中使用Objective-C类 在Xcode6

iOS学习笔记---oc语言第三天

继承.初始化方法 一.继承 继承的上层:父类  继承的下层:子类 继承是单向的,不能相互继承 继承具有传递性:A继承于B,B继承于C,A具有B和C的特征和行为 子类能继承父类全部的特征和行为(私有变量也继承过来了,只是不能访问) 面向对象提供了继承语法.能大大简化代码,把公共的方法和实例对象写在父类里.子类只需要写自己独有的实例变量和方法即可 继承既能保证类的完整,又能简化代码 继承特点 oc中只允许单继承 没有父类的类称为根类,oc中得根类是NSObject(祖宗) 继承的内容:所有的实例变量

iOS: 学习笔记, Swift与Objective-C混用总结

Swift与Objective-C交互总结 在Swift中使用Objective-C(简单) 在创建OjbC文件时, XCode会提示创建XXX-Bridging-Header.h文件, 创建之 在创建的XXX-Bridging-Header.h上导入需要引入到Swift中的Objective-C类 #import "Need.h" 然后在Swfit中就能使用它了 在Ojbective-C中使用Swift(非常简单) 在相应的OjbC文件中加入 #import "XXX-Sw

iOS: 学习笔记, 用代码驱动自动布局实例(swift)

iOS自动布局是设置iOS界面的利器.本实例展示了如何使用自动布局语言设置水平布局, 垂直布局1. 创建空白iOS项目(swift)2. 添加一个控制器类, 修改YYAppDelegate.swift文件 @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(application: UIApplication, didFi

iOS: 学习笔记, 值与引用类型(译自: https://developer.apple.com/swift/blog/ Aug 15, 2014 Value and Reference Type

值和引用类型 Value and Reference Types 在Swift中,有两种数据类型. 一是"值类型"(value type), 它是每一个实例都保存有各自的数据,通常定义为struct, enum或tuple. 二是"引用类型"(reference types),它是多实例共享一份数据,这种类型通常定义为class. 在本文中,我们将展示值类型和引用类型各自的优点以及如何在二者之间选择. 它们有什么区别? 最基本的区别是 "值类型"

iOS: 学习笔记, 值与引用类型(译自: https://developer.apple.com/swift/blog/ Aug 15, 2014 Value and Reference Types)

值和引用类型 Value and Reference Types 在Swift中,有两种数据类型. 一是"值类型"(value type), 它是每一个实例都保存有各自的数据,通常定义为struct, enum或tuple. 二是"引用类型"(reference types),它是多实例共享一份数据,这种类型通常定义为class. 在本文中,我们将展示值类型和引用类型各自的优点以及如何在二者之间选择. 它们有什么区别? 最基本的区别是 "值类型"

iOS: 学习笔记, Swift操作符定义

Swift操作符可以自行定义, 只需要加上简单的标志符即可. @infix 中置运算. 如+,-,*,/运算 @prefix 前置运算. 如- @postfix 后置运算. a++, a-- @assignment 赋值运算. +=, -=, --a, ++a // // main.swift // SwiftBasic // // Created by yao_yu on 14-7-27. // Copyright (c) 2014年 yao_yu. All rights reserved.

ios学习笔记图片+图片解释(c语言 oc语言 ios控件 ios小项目 ios小功能 swift都有而且笔记完整喔)

下面是目录其中ios文件夹包括了大部分ios控件的介绍和演示,swift的时完整版,可以学习完swift(这个看的是swift刚出来一周的视频截图,可能有点赶,但是完整),c语言和oc语言的也可以完整的学习完所需知识,,其他文件夹的内容如其名说描述一样 没张图片都有文字说明,可以需要该功能的时候搜索一下然后打开图片就可以学习到 网盘下载地址:需要的话给留言我再传上去 http://www.cnblogs.com/langtianya原创 ios学习笔记图片+图片解释(c语言 oc语言 ios控件