使用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
类的构造器执行了三步:
若是你不须要计算属性,可是仍然须要在设置一个新值以前或者以后运行代码,使用willSet
和didSet
。
好比,下面的类确保三角形的边长老是和正方形的边长相同。
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