《Swift开发实战》——第2章,第2.5节对象和类

2.5 对象和类
在Swift语言中,使用关键字class和类名来创建一个类。在类中声明属性的方法和声明常量、变量的方法一样,唯一的区别就是它们的上下文是类。同样,声明方法和声明函数的方法也一样。例如,下面的演示代码定义了一个名为Shape的类。

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

要想在Swift程序中创建一个类的实例,需要在类名后面加上括号,使用点语法格式来访问实例的属性和方法。例如,如下所示的演示代码。

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被用来区别实例变量。当创建一个实例的时候,像传入函数参数一样给类传入构造器的参数。每个属性都需要进行赋值操作,无论是通过声明(就像numberOfSides)还是通过构造器(就像name)。

如果要在删除对象之前进行一些清理工作,则需要使用关键字deinit创建一个析构函数。

在Swift语言中,子类的定义方法是在它们的类名后面加上父类的名字,用冒号分隔。创建类的时候并不需要一个标准的根类,所以可以忽略父类。

在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()

在Swift语言中有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")
triangle.perimeter
triangle.perimeter = 9.9
triangle.sideLength

在上述perimeter的setter中,新值的名字是newValue,可以在set之后显式地设置一个名字。其中类EquilateralTriangle的构造器执行了如下所示的3个操作步骤。

设置子类声明的属性值。
调用父类的构造器。
改变父类定义的属性值。其他的工作,比如调用方法、getters和setters,也可以在这个阶段完成。
如果不需要计算属性,但是仍然需要在设置一个新值之前或者之后运行代码,可使用willSet和didSet。
又比如在下面的演示代码中,类TriangleAndSquar可以确保三角形的边长总是和正方形的边长相同。

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

在Swift语言中,类中的方法和一般函数的重要区别如下所示。

函数的参数名只在函数内部使用。
方法的参数名需要在调用的时候显式说明(除了第一个参数)。在默认情况下,方法的参数名和它在方法内部的名字一样,不过也可以定义第二个名字,这个名字被用在方法内部。
例如,如下所示的演示代码。

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

在Swift语言中,处理变量的可选值时可以在操作(比如方法、属性和子脚本)之前加“?”。如果“?”之前的值是nil,“?”后面的东西都会被忽略,并且整个表达式返回nil;否则,“?”之后的东西都会被运行。在上述两种情况下,整个表达式的值也是一个可选值。例如,如下所示的演示代码。

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength
时间: 2024-10-02 17:29:26

《Swift开发实战》——第2章,第2.5节对象和类的相关文章

《Swift开发实战》——第16章,第16.1节下标脚本语法

第16章 下标脚本 Swift开发实战 在Swift语言中,类(class).结构体(structure)和枚举(enumeration)等目标中定义下标脚本,被认为是访问对象.集合或序列的快捷方式,不需要再调用实例的特定的赋值和访问方法.在本章的内容中,将详细讲解Swift下标脚本的基本知识. 16.1 下标脚本语法 在Swift语言中,可以使用下标脚本访问一个数组(Array)实例中的元素,参见如下所示的格式. someArray[index] 在访问字典(Dictionary)实例中的元素

《Swift开发实战》——第2章,第2.1节千里之行,始于足下——Swift语言基础

第2章 千里之行,始于足下--Swift语言基础 Swift开发实战 Swift 是一种适用于 iOS 和 OS X 应用开发的全新编程语言,它建立在C和Objective-C语言基础之上,并且没有C语言的兼容性限制.Swift 采用安全的编程模式,增加了现代功能,使编程更容易.更灵活.更有趣.Swift 以成熟且备受宠爱的Cocoa和 Cocoa Touch 框架作为支撑,这是一个重新构建软件开发的机会.本章将带领大家学习Swift这门神奇语言的基本语法知识,为读者步入本书后面知识的学习打下基

《Swift开发实战》——第1章,第1.1节Swift概述

第1章 工欲善其事,必先利其器--Swift语言基础Swift开发实战Swift是苹果公司在WWDC2014大会上所发布的一门全新的编程语言,用于编写OS X和iOS应用程序.苹果公司在设计Swift语言时,就有意让其和Objective-C共存,Objective-C是苹果操作系统在导入Swift前使用的编程语言.本章将带领大家初步认识Swift这门神奇的开发语言,让读者为学习本书后面的知识打下基础. 1.1 Swift概述Swift是一种为开发iOS和OS X应用程序而推出的全新编程语言,是

《Swift开发实战》——导读

目 录 内容简介 前 言 第1章 工欲善其事,必先利其器--Swift语言基础 1.1节Swift概述1.2节搭建开发环境1.3节使用Xcode开发环境1.4节启动iOS 8模拟器 第2章 千里之行,始于足下--Swift语言基础2.1节千里之行,始于足下--Swift语言基础2.2节简单值2.3节流程控制2.4节函数和闭包2.5节对象和类2.6节枚举和结构体2.7节协议和扩展2.8节泛型 第3章 新语言,新特性--Swift的基础语法 第4章 运算符 第5章 字符串和字符 第6章 表达式 第7

《Swift开发实战》——第1章,第1.2节搭建开发环境

1.2 搭建开发环境都说"工欲善其事,必先利其器",这一说法在编程领域同样行得通,学习Swift开发也离不开好的开发工具的帮助.在本节中,将详细讲解搭建Swift语言开发环境的基本知识. 1.2.1 Xcode 6介绍要开发iOS的应用程序,需要一台安装有Xcode工具的Mac OS X电脑.Xcode是苹果提供的开发工具集,它提供了项目管理.代码编辑.创建执行程序.代码调试.代码库管理和性能调节等功能.这个工具集的核心就是Xcode程序,提供了基本的源代码开发环境. Xcode是一款

《Swift开发实战》——第2章,第2.2节简单值

2.2 简单值 在Swift语言中,使用关键字"let"来声明常量,使用关键字"var"来声明变量.对于一个Swift常量值来说,在编译时并不需要有一个明确的值,但是只能为这个常量赋值一次.也就是说,可以用常量来表示一个只需要决定一次但是需要使用很多次的值.例如,在本章前面的实例2-1中,如下都是声明常量值的实现代码. var value=123; var i:Int = 0; var num=0; 常量或者变量的类型必须和赋给它们的值一样,在进行声明操作时,可以选

《Swift开发实战》——第1章,第1.4节启动iOS 8模拟器

1.4 启动iOS 8模拟器 Xcode是一款功能全面的应用程序,通过此工具可以轻松输入.编译.调试并执行Swift程序.如果想在Mac上快速开发iOS应用程序,则必须学会使用这个强大的工具的方法.接下来将简单介绍使用Xcode编辑启动模拟器的基本方法. (1)Xcode位于"Developer"文件夹内中的"Applications"子文件夹中,快捷图标如图1-48所示. (2)启动Xcode 6后的初始界面如图1-49所示,在此可以设置创建新工程还是打开一个已存

《Swift开发实战》——第2章,第2.4节函数和闭包

2.4 函数和闭包 在本章前面的实例2-1中,testfunc就是一个函数.在Swift语言中,使用关键字func来声明一个函数,使用名字和参数来调用函数,使用"→"来指定函数返回值.例如,如下所示的演示代码. func greet(name: String, day: String) -> String { return "Hello \(name), today is \(day)." } greet("Bob", "Tues

《Swift开发实战》——第2章,第2.3节流程控制

2.3 流程控制在本章前面的实例2-1程序中,下面这些都是实现流程控制工作的实现代码. switch("abc") { case "123": println("123"); case "456","abc": println("123 abc "); default: println("没有找到合适的匹配"); } var i:Int = 0; while( i&l