对象和类

使用class和类名来建立一个类。类中属性的声明和常量、变量声明同样,惟一的区别就是它们的上下文是类。一样,方法和函数声明也同样。javascript

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

练习: 使用let添加一个常量属性,再添加一个接收一个参数的方法。php

要建立一个类的实例,在类名后面加上括号。使用点语法来访问实例的属性和方法。java

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

这个版本的Shape类缺乏了一些重要的东西:一个构造函数来初始化类实例。使用init来建立一个构造器。swift

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被用来区别实例变量。当你建立实例的时候,像传入函数参数同样给类传入构造器的参数。每一个属性都须要赋值——不管是经过声明(就像numberOfSides)仍是经过构造器(就像name)。ide

若是你须要在删除对象以前进行一些清理工做,使用deinit建立一个析构函数。函数

子类的定义方法是在它们的类名后面加上父类的名字,用冒号分割。建立类的时候并不须要一个标准的根类,因此你能够忽略父类。ui

子类若是要重写父类的方法的话,须要用override标记——若是没有添加override就重写父类方法的话编译器会报错。编译器一样会检测override标记的方法是否确实在父类中。spa

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,构造器接收两个参数,一个是半径一个是名称,在子类Circle中实现area()simpleDescription()方法。code

除了储存简单的属性以外,属性能够有 getter 和 setter 。对象

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") print(triangle.perimeter) triangle.perimeter = 9.9 print(triangle.sideLength)

perimeter的 setter 中,新值的名字是newValue。你能够在set以后显式的设置一个名字。

注意EquilateralTriangle类的构造器执行了三步:

  1. 设置子类声明的属性值
  2. 调用父类的构造器
  3. 改变父类定义的属性值。其余的工做好比调用方法、getters和setters也能够在这个阶段完成。

若是你不须要计算属性,可是仍然须要在设置一个新值以前或者以后运行代码,使用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") print(triangleAndSquare.square.sideLength) print(triangleAndSquare.triangle.sideLength) triangleAndSquare.square = Square(sideLength: 50, name: "larger square") print(triangleAndSquare.triangle.sideLength)

处理变量的可选值时,你能够在操做(好比方法、属性和子脚本)以前加?。若是?以前的值是nil?后面的东西都会被忽略,而且整个表达式返回nil。不然,?以后的东西都会被运行。在这两种状况下,整个表达式的值也是一个可选值。

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square") let sideLength = optionalSquare?.sideLength
相关文章
相关标签/搜索