微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Swift学习—对象和类

class后面跟类名来创建一个类。除了上下文是类以外,声明一个属性和常量,变量声明是一样的,方法函数也是如此。

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

添加一个常量属性,再添加一个一个参数的函数

通过在类名的后面加小括号来创建这个类的实例。用点语法来访问这个实例的属性方法

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

上个版本的Shape类缺失了一个重要的东西:通过初始化器来创建一个实例。用init来 创建一个

class NamedShape {
    var numberOfSides: Int = 0
    var name: String
    
    init(name: String) {
        self.name = name
    }
    
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}

值得注意的是这里用self来区分name属性还是参数。创建一个类的实例时这里的参数传递就像函数调用时的参数传递一样。每一个属性都需要赋值,在声明的时候(如numberOfSides)或是在初始化器中(如name)。

当你需要在对象释放前做一些清理工作,可以用deinit来创建一个析构器。

子类类名后面是父类名,中间用冒号: 隔开。没有强求子类要有标准的根类,所以可以根据需要省略父类

子类的方法要覆盖父类方法的实现时,要用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()

试一试:

一个继承自NameShape的子类Circle,初始化器中接收radiusname参数。并实现areadescribe方法

除了简单的存储属性属性还有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 triagle with sides of length \(sideLength)."
    }
}
var triangle = EquilateralTriangle(sideLength: 3.1,name: "a triangle")
triangle.perimeter
triangle.perimeter = 9.9
triangle.sideLength

perimetersetter方法中,新值有一个隐式的名newValue.你可以在set方法的后面加一个括号显式的提供一个新值名字。

对于EquilateralTriangle中的初始化器做了三件事:

1.设置子类声明的属性的值

2.调用父类的初始化器

3.改变被父类定义属性值。当然通过其他的如方法getter,setter,都可以完成这一点。

如果你不需要计算属性但是又需要在设置一个新值之后,在运行之前提供一些代码,可以用willsetdidset。比如,下面的类确保了三角形和正方形的边长都相同。

class TriangleAndSquare {
    var triangle: EquilateralTriangle {
    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 = EquilateralTriangle(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.incrementBy(2,numberOfTimes: 7)

当用到optional值时,你可以在操作之前加一个问号。如果在之前的值是nil,那么问号之后的代码就被忽略,都被视为是nil。否则,这个optional值被解包,问号之后的就作为解包值。下面两种情况下,整个表达式的值都是一个optional值。

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

原文地址:https://www.jb51.cc/swift/327117.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐