Swift简明教程(四)类与对象

7 篇文章 0 订阅

Swift简明教程(四)类与对象


Swift中使用class关键字定义类。类里面属性的声明与定义变量和常量差不多,而成员方法也与普通函数的写法一样,只是写在类里面。

class Shape {
    var numberOfSides = 0
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}


试验
给上面的类用let添加一个常量属性,并且增加一个能够接受一个参数的方法


直接在类名后增加圆括号就可以创建这个类的实例,然后通过点操作符访问它的属性和成员方法。

var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()


不过上面的Shape类还缺少一些重要的东西:在创建对象的时候进行初始化的初始化器。初始化器用init进行定义。

class NameShape {
    var numberOfSides: Int = 0
    var name: String

    init(name: String) {
        self.name = name
    }

    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}


这里要注意的是init方法中self的用法。初始化方法的参数传递与普通的函数类似。类中的属性都应该进行初始化赋值,不管是在声明的时候还是在初始化器中。


deinit是Swift的析构函数,与dealloc类似,用在对象销毁时进行清理工作。


在类名后使用冒号:和父类的名字表示继承关系,Swift中并不要求每个类都有父类。


子类使用override关键字来重写父类的方法,如果没有写override的话,会出现编译器错误。同样,编译器也会检查带有override关键字的方法是否真的重写了父类的方法。

class Square : NamedShape {
    var sideLength: Double

    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 4
    }

    func area() -> Double {
        return sideLength * sideLength
    }

    override func simpleDescription() -> String {
        return "A square with sides of length \(sideLength)."
    }
}

let test = Square(sideLength: 5.2, name: "my test square")
test.area()
test.simpleDescription()


试验NamedShape创建一个叫Circle的子类,使它能够接受一个半径和名字作为参数。然后实现areadescribe方法。


与Objective-C类似,Swift还能给属性定义gettersetter

class EquilateralTriangle: NamedShape {
    var sideLength: Double = 0.0

    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)

        numberOfSides = 3
    }

    var perimeter: Double {
        get {
            return 3.0 * sideLength
        }
        set {
            sideLength = newValue / 3.0
        }
    }

    override func simpleDescription() -> String {
        return "An equilateral triangle with sides of length \(sideLength)."
    }
}

var triangle = EquilateralTraingle(sideLength: 3.1, name: "a triangle")
triangle.perimeter
triangle.perimeter = 9.9
triangle.sideLength


perimeter的设置方法中,新的值默认存放在newValue变量里。当然,也可以显式的在set方法后的圆括号中提供变量名字。


注意EquilateralTriangle类的初始化器里有三步:
  1. 设置子类中定义的属性的值。
  2. 调用父类的初始化器
  3. 改变父类中定义的属性的值。


如果你不需要计算属性的值,但是想要在属性的值发生改变之前或者改变后执行一些任务,可以使用willSetdidSet。例如下面的代码可以保证三角形和四边形的边长总是相同的。

class TriangleAndSquare {
    var triangle: EquilateralTraingle {
        willSet {
            square.sideLength = newValue.sideLength
        }
    }

    var square: Square {
        willSet {
            triangle.sideLength = newValue.sideLength
        }
    }

    init(size: Double, name: String) {
        square = Square(sideLength: size, name: name)
        triangle = EuilateralTriangle(sideLength: size, name: name)
    }
}

var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
triangleAndSquare.square.sideLength
triangleAndSquare.triangle.sideLength
triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
triangleAndSquare.triangle.sideLength

类的成员方法与函数有一个非常重要的区别。函数里的参数名只能在函数体里面使用,而方法的参数名可以在调用的时候使用。

class Counter {
    var count: Int = 0
    func incrementBy(amount: Int, numberOfTimes times: Int) {
        count += amount * times
    }
}

var counter = Counter()
counter.imcrementBy(2, numberOfTimes: 7)


使用选项(Optional)的时候,可以在方法、属性等操作符前使用?。如果选项的值为nil则忽略执行?后的表达式,并且整个表达式的值为nil。否则就执行?后的表达式。

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optinal square")
let sideLength = optionalSquare?.sideLength

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值