六、swift3.0类的使用

一、类的定义

Swift也是一门面向对象开发的语言,面向对象的基础是类,类产生了对象
class是Swift中的关键字,用于定义类

在seift中,默认同一个项目中所有的类都是共享的,可以直接访问,不需要import。

在swift中所有的类都有一个命名空间,默认就是项目名称。cocopods所有的类和项目中的类在不同的命名空间里,因此可以保证类名不冲突

class 类名 : SuperClass {
    // 定义属性和方法
}
注意:

定义的类,可以没有父类。那么该类是rootClass
通常情况下,定义类时,继承自NSObject(非OC的NSObject)

//没有父类的类,就没有父类的方法和属性
class Person {
    var age : Int = 0
    
}

class Human : NSObject {
    var name : String = "zhangsan"
    
    override func setValue(_ value: Any?, forUndefinedKey key: String) {
        //利用kvc赋值时,类中没有某个属性时,重写该方法可以避免系统崩溃
    }
}

let obj1 = Person()
obj1.age = 18

let obj2 = Human()
obj2.name = "lisi"
obj2.setValue("wangwu", forKey: "name")
print(obj1.age, obj2.name)


二、类的属性

Swift中类的属性有多种,类的属性必须有值
1、存储属性:存储实例的常量和变量

swift 要求实例存储属性必须能获得初始值,即:要么将其定义为可选类型,系统会默认初始化为nil;要么定义时指定初始值;要么在构造器中指定初始值。

2、计算属性:通过类中其它属性的某种方式计算出来的属性

计算属性并不存储实际的值,而是提供一个getter和一个可选的setter来间接获取和设置其它属性。
计算属性一般只提供getter方法
如果只提供getter,而不提供setter,则该计算属性为只读属性,并且可以省略get{}

//任何你一个类的属性定义是必须有一个初始化值
class Person : NSObject {
    //1、定义存储属性
    var name : String?
    var heigh : Double = 1.85
    
    var chinaese : Double = 0.0
    var english : Double = 0.0
    
    //2、定义一个计算属性 : 通过别的属性计算的结果的属性
    var avergaeNum : Double {
        return (chinaese + english) / 2
    }
    
    // 计算属性
    var averageScore : Double {
        get {
            return (chinaese + english) / 2
        }
        
        // 没有意义,因为之后获取值时依然是计算得到的
        // newValue是系统分配的变量名,内部存储着新值
        set {
            self.averageScore = newValue
        }
    }

}

3、类属性:与整个类自身相关的属性,而不是对象。类属性的设置和修改,需要通过类来完成。

//任何你一个类的属性定义是必须有一个初始化值
class Person : NSObject {
    //1、定义存储属性
    var name : String?
    var heigh : Double = 1.85
    
    var chinaese : Double = 0.0
    var english : Double = 0.0
    
    //2、定义一个计算属性 : 通过别的属性计算的结果的属性
    var avergaeNum : Double {
        return (chinaese + english) / 2
    }
    
    
    //3、定义类属性,类属性是和类相关的属性,需要通过类名访问。定义单例时使用
    static var course : Int = 0
    
    
    //定义一个方法,返回平均成绩
    func getAverage() -> Double {
        //在swift中使用当前类的属性和方法,可以不加self
        return (chinaese + english) / 2
    
    }
}

let man = Person()
man.name = "zhangsan"
man.heigh = 1.65

let average = man.avergaeNum

//给类属性赋值
Person.course = 12

print(man.heigh)

if let name = man.name {
    print(name)
}

三、类的构造函数(init)

1、构造函数的简介

默认情况下载创建一个类时,必然会调用一个构造函数(init),进行分配空间,初始化成员变量。
即便是没有编写任何构造函数,编译器也会提供一个默认的构造函数。

构造函数是一种特殊的函数,主要用来在创建对象时初始化对象,为对象成员变量设置初始值。在 OC 中的构造函数是 initWithXXX,在 Swift 中由于支持函数重载,所有的构造函数都是 init,构造函数不用写func

构造函数的执行顺序:1、先给自己的属性分配空间并赋值;2、再调用父类的构造函数给父类的属性分配内存空间并赋值

如果是继承自NSObject,可以对父类的构造函数进行重写。NSObject没有属性,只有一个成员变量“isa”

command + shift + o :快速打开某个xcode文件

//任何你一个类的属性定义是必须有一个初始化值
class Person : NSObject {
    //1、定义存储属性
    var name : String?
    var heigh : Double = 1.85
    //注意:如果是基本数据类型,不能设置为可选的,需要设置初始值,否则kVC会崩溃
    var age : Int = 0
    
    //在swift中KVC不能给私有属性赋值,而oc中可以
    private var nickName : String?
    
    //重写系统的构造函数
    override init() {
        // super.init() 系统可以隐式调用,可以不写 ,在调用父类构造函数之前,必须保证本类的属性都已经完成初始化
        print(heigh)
        
    }
    
    //自定义构造函数
    init(name : String, height : Double) {
        self.name = name
        self.heigh = height
        super.init()   //此处必须写,系统不会隐式调用
    }
    
    //1、字典转模型
    init(dict : [String : AnyObject]) {
        let tempName = dict["name"]
        //tempName是一个AnyObject?,转成String?
        //as?:转成可选类型
        name = tempName as? String
        //as!:转成确定类型
        let tempAge = dict["heigh"]
        heigh = tempAge as! Double
        //先转换为可选类型,再解包赋值
        if let age = dict["age"] as? Int { s
            elf.age = age
        }
    }
    
    //2、字典转模型
    //利用kvc实现构造方法,但是必须先调用super.init()。kvc是给对象发送消息,所以必须保证对象已经存在。
    init(dict : [String : AnyObject]) {
        super.init()
        setValuesForKeys(dict)
    }
    
    //避免字典中的键,没有属性对应,而崩溃!
    override func setValue(_ value: Any?, forUndefinedKey key: String) { }
}

    //通过构造方法创建对象
    let man = Person.init(name: "wangwu", height: 1.55)

    print(man.heigh)

    if let name = man.name {
        print(name)
    }

    let woman = Person.init(dict: ["name" : "lisi" as AnyObject, "heigh" : 1.64 as AnyObject, "age":12 as AnyObject])

    print(woman.heigh, woman.age)

    if let name = woman.name {
        print(name)
    }

2、子类的构造函数
自定义子类时,需要在构造函数中,首先为本类定义的属性设置初始值
然后再调用父类的构造函数,初始化父类中定义的属性
可选属性是在设置数值的时候才分配空间的,是延迟分配空间的


3、函数的重载和重写的定义

重载:函数名相同,参数名/参数类型/参数个数不同,重载函数并不仅仅局限于构造函数,函数重载是面相对象程序设计语言的重要标志,函数重载能够简化程序员的记忆
OC 不支持函数重载,OC 的替代方式是 withXXX...
重写:子类需要在父类拥有方法的基础上进行扩展,需要 override 关键字



四、监听类的属性改变
在OC中我们可以重写set方法来监听属性的改变,而在Swift中可以通过属性观察者来监听和响应属性值的变化。通常是监听存储属性和类属性的改变。(对于计算属性,我们不需要定义属性观察者,因为我们可以在计算属性的setter中直 接观察并响应这种值的变化)


通过如下方法监听:
willSet:在属性值被存储之前设置。此时新属性值作为一个常量参数被传入。该参数名默认为newValue,我们可以自己定义该参数名
didSet:在新属性值被存储后立即调用。与willSet相同,此时传入的是属性的旧值,默认参数名为oldValue
willSet与didSet只有在属性第一次被设置时才会调用,在初始化时,不会去调用这些监听方法

class Person : NSObject {
    
    //属性监听器
    var name : String? {
        //属性即将改变时监听
        willSet {
            print("1111")
            print(newValue)
        }
        //属性已经改变时监听,一边直接在该方法中监听
        didSet {
            print("2222")
            print(oldValue)
        }
        
    }
    var heigh : Double = 1.85
    
    static var age : Int = 12
    
}

let man = Person()
man.name = "zhangsan"
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
 

你可能感兴趣的:(swift)