方法

286 阅读5分钟

在面向对象分析与设计方法学(OOAD)中,类是由属性和方法组成的,方法用于完成某些操作,完成计算数据等任务。

在Swift中方法是在枚举、结构体或类中定义的函数。方法是具有面向对象的特点,与属性类似,方法可以分为:实例方法和静态方法。

实例方法

实例方法与实例属性类似,都隶属于枚举、结构体或类的个体,即实例。通过实例化这些类型,创建实例,使用实例调用的方法。

class Account {
    var amount : Double = 10_000.00     //账户金额
    var owner : String = "Tony"         //账户名
    
    //计算利息
    func interestWithRate(rate : Double) -> Double {
        return rate * amount
    }
}

var myAccount = Account()
//调用实例方法
print(myAccount.interestWithRate(0.88))

使用规范的命名 在Swift中,方法和函数的主要区别有以下3个。

  • 方法的调用前面要有主体,而函数不需要。
  • 方法是在枚举、结构体或类内部定义的。
  • 方法命名规范与函数不同。

在Swift中,方法命名规范不仅仅是为了增强代码的可读性,更多的是出于与Objective-C混合编程需要。Swift要求使用规范的命名是有历史原因的,目前苹果为iOS和Mac OS X应用开发提供的开发语言是Objective-C和Swift,同一个API两种语言共存。

class Employee {
    var no : Int = 0
    var name : String = ""
    var job : String?
    var salary : Double = 0
    var dept : Department?
}

class Department {
    var no : Int = 0
    var name : String = ""
    var employees : [Employee] = [Employee]()
    
    func insertWithObject(anObject : AnyObject, atIndex index : Int) -> () {
        let emp = anObject as! Employee
        employees.insert(emp, atIndex: index)
    }
}

var dept = Department()

var emp1 = Employee()
dept.insertWithObject(emp1, atIndex: 0)

var emp2 = Employee()
dept.insertWithObject(emp2, atIndex: 0)

var emp3 = Employee()
dept.insertWithObject(emp3, atIndex: 0)

print(dept.employees.count)

如果在方法中不指定外部参数名,而是以本地参数作为外部参数名,则修改示例代码如下:

......
func insertWithObject(anObject : AnyObject, index : Int) -> () {
    let emp = anObject as Employee
    employees.insert(emp, atIndex : index)
}
......
dept.insertWithObject(emp1, atIndex: 0)

提示:如果insertWithObjective是函数,index参数前面是要加"#"号的。代码如下:

func insertWithObject(anObject : AnyObject, #index : Int) -> () {......}

结构体和枚举方法变异

结构体和枚举中的方法默认情况下是不能修改属性的。 将之前的Department定义改成结构体,代码如下:

class Employee {
    var no : Int = 0
    var name : String = ""
    var job : String?
    var salary : Double = 0
    var dept : Department?
}

struct Department {
    var no : Int = 0
    var name : String = ""
    
    var employees : [Employee] = [Employee]()
    
    func insertWithObject(anObject : AnyObject, index : Int) -> () {
        let emp = anObject as! Employee
        employees.insert(emp, atIndex: index)//编译错误
    }
}

var dept = Department()

var emp1 = Employee()
dept.insertWithObject(emp1, index: 0)

var emp2 = Employee()
dept.insertWithObject(emp2, index: 0)

var emp3 = Employee()
dept.insertWithObject(emp3, index: 0)

print(dept.employees.count)

上述代码有一行会发生编译错误,错误信息如下:

Playground execution failed: 结构体和枚举方法变异.playground:13:9: error: cannot use mutating member on immutable value: 'self' is immutable
        employees.insert(emp, atIndex: index)
        ^~~~~~~~~
结构体和枚举方法变异.playground:11:5: note: mark method 'mutating' to make 'self' mutable
    func insertWithObject(anObject : AnyObject, index : Int) -> () {
    ^
    mutating

employees属性不可以修改,如果要修改,就要将方法声明为变异的(mutating)。修改方法声明如下:

......
mutating func insertWithObject(anObject : AnyObject, index : Int) -> () {
        let emp = anObject as! Employee
        employees.insert(emp, atIndex: index)
    }
......

我们在枚举和结构体方法前面添加关键字mutating,将方法声明为变异方法,变异方法能够修改变量属性,但不能修改常量属性。


静态方法

与静态属性类似,Swift中还定义了静态方法,也称为类型方法,所谓“类型”是指枚举、结构体和类。静态方法定义的方法也是与静态属性类似的,枚举和结构体的静态方法使用的关键字是static,类的静态方法使用的关键字是class。

结构体中静态方法

一个结构体静态方法示例,代码如下:

 struct Account {
    var owner : String = "Tony"     //账户名
    static var interestRate : Double = 0.668        //利率
    
    static func interestBy(amount : Double) -> Double {
        return interestRate * amount
    }
    
    func messageWith (amount : Double) -> String {
        var interest = Account.interestBy(amount)
        return "\(self.owner) 的利息是\(interest)"
    }
    
}

//调用静态方法
print(Account.interestBy(10_000.00))


var myAccount = Account()
//调用实例方法
print(myAccount.messageWith(10_000.00))

代码var owner : String = "Tony"声明了实例属性owner,代码static var interestRate : Double = 0.668声明了静态属性interestRate,代码static func interestBy(amount : Double) -> Double { return interestRate * amount }定义静态方法interestBy,静态方法与静态计算属性类似,它不能访问实例属性或实例方法。代码func messageWith (amount : Double) -> String { var interest = Account.interestBy(amount) return "(self.owner) 的利息是(interest)" }是定义实例方法messageWith,实例方法能访问实例属性和方法,也能访问静态属性和方法。其中self是一个隐藏属性,指代当前类型实例,一般情况下不要使用它,除非属性名与变量或常量名发生冲突。

提示:Swift的静态方法中也能使用self,这在其他面向对象的计算机语言中是不允许的。此时self表示当前数据类型,不代表枚举、结构体或类的实例。

枚举中静态方法

一个枚举静态方法示例:

enum Account {

    case 中国银行
    case 中国工商银行
    case 中国建设银行
    case 中国农业银行
    
    static var interestRate : Double = 0.668    //利率
    
    static func interestBy(amount : Double) -> Double {
        return interestRate * amount
    }
}

//调用静态方法
print(Account.interestBy(10_000.00))

代码static var interestRate : Double = 0.668声明了静态属性interestRate,代码static func interestBy(amount : Double) -> Double { return interestRate * amount }定义静态方法interestBy,静态方法与静态计算属性类似,它不能访问实例属性或实例方法。

结构体和枚举的静态方法使用定义没有区别。

类中静态方法

类方法示例:

class Account {
    var owner : String = "Tony"
    
    class func interestBy(amount : Double) -> Double {
        return 0.8886 * amount
    }
}

//调用静态方法
print(Account.interestBy(10_000.00))

代码class func interestBy(amount : Double) -> Double { return 0.8886 * amount }使用关键字class定义静态方法interestBy,静态方法与静态计算属性类似,它不能访问实例属性或实例方法。