Swift学习笔记-面向对象3

//继承
//语法
/*
修饰符 class SubClass : SuperClass
{
//类定义部分
}
*/
class Fruit {
    var weight = 0.0
func info()
{
    println("我是一个水果,重\(weight)")
    }
}
//定义Fruit类的子类Apple
class Apple : Fruit
{
    var name : String!
    func taste()
    {
        println("\(name)吃起来很好吃")
    }
}
//使用该实例
var a = Apple()
a.weight = 56
a.name = "红富士"
a.info()//我是一个水果,重56.0
a.taste()//红富士吃起来很好吃
//重写父类的方法
class Bird
{
    func fly()
    {
        println("我在天空里自由自在的飞翔。。。")
    }
}
class Ostrich : Bird {
    //override 方法重写,同名方法覆盖
    override func fly() {
        println("我只能在地上跑")
    }
}
var o = Ostrich()
o.fly()//我只能在地上跑

//重写父类的属性
//重写父类的属性时一样需要使用override修饰符
class Bird1 {
    var speed : Double = 0
}
class Ostrich1 : Bird1 {
    //重写bird1的属性
    override var speed : Double {
        get {
            println("正在访问被重写的属性")
            return super.speed
        }
        set {
            super.speed = newValue * newValue
        }
    }
}
//创建Ostich1实例
var os = Ostrich1()
os.speed = 20.0
println(os.speed)//400.0

//重写属性观察者
//父类还是Bird1
class Ostrich2 : Bird1
{
    //重写Bird类的speed属性,添加属性观察者
    override var speed : Double {
        didSet{
            //属性值改变后,会自动执行该方法
            super.speed *= speed
        }
    }
}

var os1 = Ostrich2()
os1.speed = 20.0
println(os1.speed)//400.0
/*swift 不允许在子类中定义与父类中同名的存储属性 */


//重写父类的下标
//下面的例子中父类有一个只读下标,重写之后添加了set方法,变成读写属性
class Base {
    subscript (idx : Int) -> Int {
        get {
            println("父类的下标的get方法")
            return idx + 10
        }
    }
}
class Sub: Base {
    //重写Base下标
    override subscript(idx : Int) ->Int {
        get{
            println("重写后的get下标")
            println("通过super访问被重写之前的下标:\(super[idx])")
            return idx * idx
        }
        set {
            println("重写后的下标的setter方法传入的参数\(newValue)")
        }
    }
}

var base = Base()
println(base[7])//17
var sub = Sub()
println(sub[7])//49
//类的构造与析构
//类的指定构造器和便利构造器
/*
便利构造器前要加converience
convenience init (形参){
}
*/

//Apple1类使用便利构造器实现构造器的重载
class Apple1 {
    var name : String!
    var weight : Double
    //定义指定构造器
    init(name: String,weight: Double)
    {
        self.name = name
        self.weight = weight
    }
    //便利构造器,使用convenience修饰
    convenience init(n name: String,w weight: Double)
    {
        //便利构造器必须调用一个类中得其他构造器
        self.init(name:name,weight:weight)
        self.name = name
    }
}
var app1 = Apple1(n: "junjun", w: 12)
println(app1.name)
var app2 = Apple1(name: "yuyu", weight: 13)
println(app2.name)

//两段式构造
class Fruit1 {
    var name : String
    init(name: String)
    {
        self.name = name
    }
}

class Apple5: Fruit1 {
    var color : String
    init (color: String)
    {
//        println(self.color)//初始化之前不可使用本类定义的实例存储属性。编译报错
        //必须先初始化当前类定义的存储属性
        self.color = color
        //可以访问当前类定义的实例存储属性
        println(self.color)
        //重新赋值
        self.color = "红色"
//        println(super.name)//不可使用父类定义的实例存储属性。编译错误
        super.init(name: "红花果")
        //可以访问父类定义的实例存储属性
        println(super.name)
        super.name = "红富士"
    }
}

var aa = Apple5(color: "绿色")
println(aa.name)
//使用is运算符检查类型
//声明一个被Objective-C类使用的协议
@objc protocol TextProtocol{}
//声明hello时使用NSObject类,侧hello的编译时类型是NSObejct
//hello变量的实际类型是NNString
let hello : NSObject = "hello"
println("hello 是String \(hello is NSString)")//hello 是String true
//字符串是否是NSDate类型
println("hello 是 NSDate \(hello is NSDate)")//hello 是 NSDate false

//Any和AnyObject
//AnyObject:可代表任何的实例
//Any:可代表任何的类型。包括Int,Double等类型。

var anyArray : [Any] = ["swift",29,["any":90],"JiangJun"]
//遍历数组元素为Anyde 数组
for element in anyArray {
    if element is NSString{
        println(element)
    }
}
//定义元素类型为AnyObject的数组,该数组的元素只能是对象
var anyObjectArray : [AnyObject] = [Apple5(color: "红色"),Apple5(color: "蓝色")]

//嵌套类型
//扩展
/*
修饰符可以省略,也可以是private|internal|public
[修饰符]extension 已有类型
{
//添加新的功能
}

扩展协议
[修饰符] extension 已有类型 : 协议1,协议2
{
//实现方法
}
*/

//使用扩展不能添加实例存储属性,下面使用扩展来增加String的功能
extension String
{
    //通过扩展增加类型存储属性
    static var data : [String:Any] = [:]
    //定义一个计算属性。并添加getter,setter方法部分
    var length: Int {
        get{
            return count(self)
        }
        set{
            var originLength = count(self)
            //如果新设置的长度大于字符串原来长度,侧在字符串后面添加空字符
            if newValue > originLength {
                for idx in 1...originLength {
                    self += ""
                }
            }
            //如果新设置的长度小于字符串原有的长度,侧将后面多余的字符截断
            else if newValue < originLength
            {
                var tmp = ""
                var count = 0
                for ch in self
                {
                    tmp = "\(tmp) \(ch)"
                    count++
                    //如果已经拼接了newValue个字符,则跳出循环
                    if count == newValue{
                        break
                    }
                }
                self = tmp
            }
        }
    }
}

String.data["swift"] = 89
String.data["OC"] = 92
println(String.data)

var s = "fkit,org"
println(s.length)
s.length = 5
println(s)//f k i t ,
s.length = 20
println(s)//f k i t ,后面还有15个空格

*/
///
extension String
{
    //添加一个新方法,用于获取当前字符串中指定中指定的范围的字符串
    func subsrtingFromStrart(start : Int, toEnd : Int) -> String
    {
        var count = 0
        var tmp = ""
        for ch in self
        {
            //从start开始获取字符
            if count >= start
            {
                tmp = "\(tmp)\(ch)"
            }
            //获取到toEnd处结束,程序不再需要后面的字符
            if count >= toEnd - 1
            {
                break
            }

            count++
        }
        return tmp
    }
    //定义一个类方法,该类方法用于将bool值转换为字符串
    static func valueOf(value : Bool) -> String {
        return "\(value)"
    }
}

var str = "fkit.orgisagoodcenter"
//截取原字符串中索引为5开始,到索引为10之间的子串
var subStr = str.subsrtingFromStrart(5, toEnd: 10)
println(subStr)//orgis
println(String.valueOf(true));//true

//添加可变方法,类不可以定义可变方法,
//下面方法用于计算当前数组与另一个数组的交集
extension Array
{
    //定义一个方法,用于计算数组的交集
    mutating func retainAll(array : [T],compartor : (T,T) -> Bool)
    {
        var tmp = [T]()
        //遍历当前数组中所有元素
        for ele in self
        {
            //遍历第二个数组的所有的元素
            for target in array
            {
                //如果两个元素通过compartor比较返回true
                if compartor(ele ,target)
                {
                    tmp.append(ele)
                    break
                }
            }
        }
        self = tmp
    }
}

var books = ["ios","Android","swift","Java","Rudy"]
books.retainAll(["Android","swift","xuexi"]){
    return $0 == $1
}
println(books)//[Android, swift]

//使用扩展添加构造器
//定义一个结构体不包含任何构造器,系统将为之提供1个默认的构造器
struct SomeStruct
{
    var name : String
    var count : Int
}

//使用扩展来添加构造器
extension SomeStruct
{
    //通过扩展添加的2个构造器对该类型原有的构造器没有影响
    init(name:String)
    {
        self.name = name
        self.count = 0
    }
    init(count:Int)
    {
        self.count = count
        self.name = ""
    }
}
//下面使用了SomeStruct的3个构造器,其中第一个构造器是系统提供的
var sc1 = SomeStruct(name: "fkit", count: 3)
var sc2 = SomeStruct(name: "JiangJun")
var sc3 = SomeStruct(count: 5)

//使用扩展添加嵌套类型
//下面为String添加枚举
extension String
{
    //定义一个嵌套枚举
    enum Suit : String
    {
        case Diamond = "♦️"
        case Clud = "♣️"
        case Heart = "❤️"
    }
    //通过扩展为String添加一个类型方法,用于判断指定字符串属于那种花色
    static func judgeSuit(s: String) -> Suit?
    {
        switch(s)
        {
            case "♦️":
            return .Diamond
            case "♣️":
            return .Clud
            case "❤️":
            return .Heart
        default:
            return nil
        }
    }
}

//使用String包含的嵌套枚举
var s1: String.Suit? = String.judgeSuit("❤️")
println(s1)//Optional((Enum Value))
var s2: String.Suit? = String.judgeSuit("j")
println(s2)//输出nil

//协议
/*
语法格式
修饰符:private, internal, public
[修饰符] protocol 协议名 : 父协议1,父协议2...
{
//协议内容
}

2.实现协议
struct 结构体名:FirstProtocol,AnotherProtocol,...
{
//实现协议要求
}

3.类不仅可以实现多个协议,还可以实现协议时继承一个父类,此时需要把所有的父类放在协议之前
class 类名:SuperClass,FirstProtocol,AnotherProtocol,...
{
//实现协议要求
}
4.协议指定的属性要求
[class ] var 属性名:类型{get [set]}
class:可有可无,有说明要求定义类型属性;无说明定义的是实例属性。此处不可使用staic代替class
此处只要get,set即可无须提供实现,其中set可有可无,如果有set侧要求该实现者必须提供与之匹配的读写属性;如果没有set,侧只要求该实现者提供与之匹配的只读属性
*/

//描边属性,画笔的粗细
protocol Strokable
{
    var strokeWidth : Double{get set}
}
//填充颜色,定义一个枚举作为协议属性的类型,由于协议并不支持嵌套类型,因此程序只能将枚举定义在协议之外
protocol Fullable
{
    var fullColor : Color? {get set}
}

enum Color
{
    case Red,Green,Blue,Yellow,Cyan
}

//定义一个协议,并让该协议实现两个父协议
protocol HasArea : Fullable, Strokable
{
    var area : Double {get}
}
//下面定义一个协议,该协议包含两个类型属性要求,协议中得类型属性使用class关键字修饰
protocol Mathable
{
    static var pi: Double {get}
    static var e: Double {get}
}

//让Rect实现两个协议
struct Rect: HasArea, Mathable
{
        var width: Double
        var height: Double
        init(width:Double , height:Double)
        {
    self.width = width
    self.height = height
        }
        //使用存储属性实现Fullable协议的fullColor属性
        var fullColor: Color?
        var strokeWidth: Double = 0.0
        var area: Double {
            get{
            return width * height
            }
        }
        //通过存储属性实现Mathable协议要求的两个类型属性
        //虽然协议中使用class关键字定义类型属性,但值类型中依然使用static定义类型属性
        static var pi: Double = 3.14159535
        static var e: Double = 2.71828
}
//下面定义一个Circle类,该类同样实现了。上面的HasArea和Mathable两个协议
class Circle: HasArea, Mathable
{
    var radius:Double
    init (radius:Double)
    {
        self.radius = radius
    }
    //使用存储属性实现Fullable协议的Fullcolor属性
    var fullColor:Color?
    //使用存储属性实现HasArea协议的StrokeWidth属性
    var strokeWidth:Double = 0.0
    //使用存储属性实现HasArea协议要求的area属性
    var area: Double {
        get{
            return Circle.pi * radius * radius
        }
    }
    //通过存储属性实现Mathable协议要求的两个类型属性
    //由于类不支持定义类型存储属性,只能使用类型计算属性
    class var pi:Double {return 3.14159535}
    class var e:Double {return 2.71828}
}
var rect = Rect(width: 4.5, height: 4.0)
println(rect.area)//18.0
rect.fullColor = Color.Red
rect.strokeWidth = 1.0
println(rect.fullColor)//Optional((Enum Value))
println(rect.strokeWidth)//1.0
var circle = Circle(radius: 2.0)
println(circle.area)
circle.fullColor = Color.Green
circle.strokeWidth = 0.5

//协议指定的方法要求
protocol Eatable
{
    //定义实例方法
    func taste()
    static func test(msgs: String...)
}

//结构体实现Eatable协议
struct Pie : Eatable
{
    var weight:Double
    //定义实例方法
    func taste() {
        println("\(weight)斤饼干吃起来香脆可口")
    }
    //结构体使用static修饰类型方法
    static func test(msgs: String...) {
        println("饼干实现的test方法")
        for msg in msgs
        {
            println("个数可变的形参:\(msg)")
        }
    }
}

//实现Eatable协议
class Apple1:Eatable
{
    var name:String
    init(name:String)
    {
        self.name = name
    }
    //定义实例方法
    func taste() {
        println("\(name)水分充足,营养丰富")
    }
    //类使用class修饰类型方法
    class func test(msgs: String...) {
        println("苹果实现的test方法")
        for msg in msgs
        {
            println("个数可变的形参:\(msg)")
        }
    }
}

Pie.test("饼干1","饼干2","饼干3")
var pie = Pie(weight: 2.3)
pie.taste()
//调用形参个数可变的类型方法
Apple1.test("苹果1","苹果2","苹果3")
var apple = Apple1(name: "红富士")
apple.taste()

//协议指定的可变方法要求
//可变方法使用mutating修饰,类不存在可变方法,因此类是引用类型,类中的方法本来就可以改变实例数据,枚举,结构体来实现协议中得可变方法时,也需要使用mutating修饰;但使用类实现该协议中得可变方法时,侧无需使用mutating修饰
protocol Incrementable
{
    //定义可变的实例方法
    mutating func incrementByDelta(delta:Double)
}
//上面协议定义了一个mutating修饰的可变方法,这表明结构体既可使用可变方法来实现该方法,也可使用非可变方法来实现该方法
//实现Incrementable协议
struct FkRange:Incrementable
{
    var start: Double
    var length: Double
    //实现协议中得可变方法,依然使用mutating修饰
    mutating func incrementByDelta(delta: Double) {
        self.length += delta
    }
}
//实现Incremntable协议
class Circle1 : Incrementable
{
    var radius: Double
    init(radius:Double){
        self.radius = radius
    }
    //实现协议中得可变方法,无须使用mutating修饰
    func incrementByDelta(delta: Double) {
        self.radius += delta
    }
}

var range = FkRange(start: 2.0, length: 10.0)
range.incrementByDelta(5.0)
println(range.length)//15.0
var circle1 = Circle1(radius: 3.0)
circle1.incrementByDelta(5.0)
println(circle1.radius)//8.0

//协议指定的下标要求
//协议能要求实现者必须提供哪些下标,也能要求该下标是否有setter部分和getter部分
/*
subscript(形参列表) -> 返回值 {get[set]}
此处只要写get,set即可,无须提供实现。其中set可有可无。如果有set,则要求实现者必须提供与之匹配的读写下标:如果没有set,则要求该实现者提供与之匹配的只读下标
*/
protocol Mathable3
{
    //定义两个重载的下标
    subscript(idx:Int) -> Int {get}
    subscript(a: Int, b: Int) -> Int {get}
}

//实现Mathable3协议
struct LinearStruct : Mathable3
{
    var factor: Int
    //提供getter,setter部分,使之成为读写下标
    subscript(idx: Int) ->Int
    {
        get{
            return factor * idx
        }
        set{
            println("执行LinearStruct的下标赋值")
        }
    }
    //实现只读下标
    subscript(a: Int,b: Int) -> Int
        {
        return factor * a + b
    }
}

//下面使用一个Quadratic类实现Mathable协议,也需要实现协议中得两个下标
class Quadratic: Mathable3
{
    var factor : Int
    init(factor: Int)
    {
        self.factor = factor
    }
    //实现下标
    subscript(idx: Int) -> Int
        {
        return factor * factor * idx
    }
    //实现只读下标
    subscript(a: Int,b: Int) -> Int
        {
        return factor * factor * a + b
    }
}

var q = Quadratic(factor: 5)
println(q[4])//100
println(q[4,6])//106

var line = LinearStruct(factor: 5)
println(line[4])//20
println(line[4,6])//26

//协议指定的构造器要求
//使用类实现协议,并实现协议中得构造器时,必须使用required修饰该构造器,除非该类使用了final修饰(该类不能派生子类),此时可以省略构造器的required(也可不省略)
//使用类实现协议,并实现协议中得构造器时,如果该构造器,还重写了其父类的构造器,则必须同时使用required override修饰
protocol Initable
{
    //定义两个必须被实现类所实现的协议
    init(name: String)
    init(name: String, weight: Double)
}

//实现Initable
struct  Bag : Initable
{
    var name: String
    var weight: Double
    //结构体实现协议的构造器没有太多要求
    init(name: String)
    {
        self.name = name
        self.weight = 0.0
    }
    init(name: String , weight: Double)
    {
        //调用同一个类中另外一个重载的构造器
        self.init(name:name)
        self.weight = weight
    }
}

//定义一个Apple类来实现Initable协议
class Fruit1
{
    var name: String
    init(name: String)
    {
        self.name = name
    }
}
//继承Fruit1
class Apple8 : Fruit1 , Initable
{
    var weight : Double
    //重写父类方法。并实现协议中得构造器,因此需要使用override required修饰
    override required init(name: String)
    {
        self.weight = 0.0
        super.init(name: name)
    }
    //使用便利构造器实现协议中得构造器
    required convenience init(name: String, weight: Double) {
        self.init(name: name)
        self.weight = weight
    }
}

var ap1 = Apple8(name: "红富士")
var ap2 = Apple8(name: "无花果", weight: 2.3)
println("\(ap2.name) , \(ap2.weight)")

var bag1 = Bag(name: "书包")
var bag2 = Bag(name: "旅行包", weight: 20)
println("\(bag2.name) , \(bag1.name)")

//合成协议
//swift还允许将多个协议合成一个临时的类型,这种用法为合成协议,格式
//protocol<协议1,协议2,协议3,...>,必须同时实现合成协议的所有的协议
//使用合成协议来定义arg形参
func test1(arg: protocol<HasArea,Mathable3>)
{
    /*
    编译器知道arg参数必须是HasArea的实例类型的实例
    因此arg参数有fullColor属性
    */
    println("arg的填充颜色是\(arg.fullColor)")
    //因此arg参数有strokenWidth属性
    println("arg的描边笔的粗细是\(arg.strokeWidth)")
    println("arg参数的面积是\(arg.area)")
}

var circle5 = Circle(radius: 1.2)
circle5.strokeWidth = 0.5
circle5.fullColor = Color.Red
var rect5 = Rect(width: 3.4, height: 2.8)
rect5.strokeWidth = 0.8
rect5.fullColor = Color.Green
//
//test1(circle5)
//test1(rect5)

//通过扩展为已有的类型添加协议
//定义一个Eatable协议
protocol Eatable1
{
    func taste()
}
//通过扩展让String实现Eatable1协议
extension String : Eatable1
{
    //实现Eatable1协议中得方法
    func taste() {
        println("\(self)吃起来味道不错,呵呵")
    }
}
func eat(foods : Eatable1...)
{
    //遍历foods个数的参数,foods相当于数组
    for food in foods
    {
        food.taste()
    }
}

//调用eat()方法,并传人3个String作为Eatable实例
eat("swift","oc")

//唯类协议
//只支持被类实现,不允许被枚举,结构体实现,
//定义唯类协议在协议名后的冒号后面添加class关键字即可(class放在所有父协议的第一位)
/*
protocol 协议名 : class, 父协议1,...
{
//唯类协议的定义
}
*/
protocol Movable : class
{
    func move()
}
class Car : Movable {
    func move() {
        println("汽车在飞")
    }
}

var car1 = Car()
car1.move()

//可选协议,是唯类协议,必须添加@objc修饰
@objc protocol MyProtocol
{
    //定义可选属性
    optional var status : String {get}
    //可选方法
    optional func increment(val: Int)
    //可选下标
    optional subscript(idx: Int) -> Int{get}
}
//定义一个空类来实现协议
class EmptyClass : MyProtocol {

}
//选择性的实现MyProtocol协议
class MyClass : MyProtocol
{
    var name : String
    init(name : String)
    {
        self.name = name
    }
    //实现协议中得可选属性
    var status : String
        {


        if count(name) < 10
        {
            return "良好"
            }
            else
        {
            return "超长"
            }
    }
    //实现协议中得可选方法
    func increment(val: Int) {
        println("系统正在增长长度")
        for idx in 1...val
        {
            name += "="
        }
    }
}

var mp : MyProtocol = MyClass(name: "JiangJun")
//访问属性
println(mp.status)

mp.increment?(10)
println(mp.status)

//输出实例和Printable协议
//下面定义了一个person类
class Person
{
    var name : String
    var age : Int
    init(name: String , age : Int)
    {
        self.name = name
        self.age = age
    }
    var description : String {
        //返回一个字符串
        return "name = \(self.name),age = \(age)"
    }
}
var person = Person(name: "悟空", age: 500)
println(person)
println(person.description)

//使用自定义类型作为字典的key
//重载全局的==运算符
//class User0 : Equatable
//{
//    var name : String
//    var password : String
//    var age : Int
//    init(name: String , password : String ,age : Int)
//    {
//       self.name = name
//        self.password = password
//        self.age = age
//    }
//}

猜你喜欢

转载自blog.csdn.net/JangJun521/article/details/46437099