Swift复习系列:方法

作者: ZYiDa | 来源:发表于2017-09-13 14:50 被阅读39次

Swift语言中,方法分两种:

  • 实例方法,为给定类型的实例封装 了具体的任务与功能,通过实例对象来调用;
  • 类型方法,和类型本身相关联,通过类型名称来调用。

方法(Method)使用适用于类、结构体和枚举。

结构体和枚举能够定义方法是SwiftC/Objective-C的主要区别之一。在Objective-C中,类是唯一能定义 方法的类型。但在Swift中,你不仅能选择是否要定义一个类/结构体/枚举,还能灵活地在你创建的类型(类/ 结构体/枚举)上定义方法。

实例方法(Instance Methods)

    1. 实例方法是属于某个特定类、结构体或者枚举类型实例的方法。实例方法提供访问和修改实例属性的方法或提供
      与实例目的相关的功能,并以此来支撑实例的功能。
    1. 实例方法要写在它所属的类型的前后大括号之间。实例方法能够隐式访问它所属类型的所有的其他实例方法和属
      性。实例方法只能被它所属的类的某个特定实例调用。实例方法不能脱离于现存的实例而被调用。

如下例子

class StepCounter
{
    var stepCount = 0

    func increasement()
    {
        stepCount += 1
    }

    func increasemen(by amount:Int)
    {
        stepCount += amount;
    }

    func resetCount()
    {
        stepCount = 0
    }
}


let counter = StepCounter.init()

for _ in 1...10
{
    counter.increasement()
}
print("-01-stepCounter = \(counter.stepCount)")

counter.increasemen(by: 100)
print("-02-stepCounter = \(counter.stepCount)")

counter.resetCount()
print("-03-stepCounter = \(counter.stepCount)")

输出结果

-01-stepCounter = 10
-02-stepCounter = 110
-03-stepCounter = 0
Program ended with exit code: 0

如上,和属性一样,我们可以使用.语法(dot syntax)来调用实例方法。

1. self属性

类型的每一个实例都有一个隐含属性叫做selfself 完全等同于该实例本身。你可以在一个实例的实例方法中 使用这个隐含的self属性来引用当前实例.如下,increasement()还可以这样写,

    func increasement()
    {
        self.stepCount += 1
    }

在项目我们不必经常写self.,不过当参数名和属性名称一样的情况下,参数名称享有优先权,并且在引用属性时必须使用一种更严格的方式。这时你可以使用self属性来区分参数名称和属性名称。
如下

    func increasemen(by stepCount:Int)
    {
        self.stepCount += stepCount;
    }
2. 在实例方法中修改值类型

结构体和枚举是值类型。默认情况下,值类型的属性不能在它的实例方法中被修改。但是,如果我们需要在某个特定的方法中修改结构体或者枚举的属性,可以为这个方法设置可变(mutating) 行为,然后就可以从其方法内部改变它的属性,并且这个方法做的任何改变都会在方法执行结束时写回到原始结构中。方法还可以给它隐含的self属性赋予一个全新的实例,这个新实例在方法结束时会替换现存实例。
如下例子

struct MyPoint
{
    var x = 0.0
    var y = 0.0
    mutating func moveByX(typeX:Double,typeY:Double)
    {
        self.x += typeX
        self.y += typeY
    }
}

var point = MyPoint.init(x: 10, y: 10)
print("MyPoint = \(point.x,point.y)")

point.moveByX(typeX: 11, typeY: 11)
print("Now,MyPoint = \(point.x,point.y)")

运行结果

MyPoint = (10.0, 10.0)
Now,MyPoint = (21.0, 21.0)
Program ended with exit code: 00

注意:不能在结构体类型的常量(a constant of structure type)上调用可变方法,因为其属性不能被改变,即使属性是变量属性.eg.let point02 = MyPoint.init(x: 10, y: 10) ,point02就不能修改其属性的值。

3. 在可变方法中给Self赋值

可变方法能够赋给隐含属性 self一个全新的实例,上面MyPoint的例子还可以如下写

struct MyPoint
{
    var x = 0.0
    var y = 0.0
    mutating func moveByX(typeX:Double,typeY:Double)
    {
        self = MyPoint.init(x: self.x + typeX, y: self.y + typeY)
    }
}

var point = MyPoint.init(x: 10, y: 10)
print("MyPoint = \(point.x,point.y)")

point.moveByX(typeX: 11, typeY: 11)
print("Now,MyPoint = \(point.x,point.y)")

在枚举的可变方法中,我们可以把self设置为同一枚举类型的不同成员,如下

enum SwitchType
{
    case Off,Low,High
    mutating func nextType()
    {
        switch self
        {
        case .Off:
            self = .Low
        case .Low:
            self = .High
        case .High:
            self = .Off
        }
    }
}

var lightingSwitchType = SwitchType.Off

lightingSwitchType.nextType()
print(lightingSwitchType)

lightingSwitchType.nextType()
print(lightingSwitchType)

运行结果:

Low
High
Program ended with exit code: 0

类型方法(Type Methods)

    1. 类型方法是定义在类型本身上调用的方法,这一点和Objective-C中的静态方法类似,都是通过类型名来调用该方法。
    1. 在方法的func 关键字之前加上关键字static,来指定类型方法。类还可以用关键字class来允许子类重写 父类的方法实现
    1. Objective-C中,你只能为Objective-C的类类型(classes)定义类型方法(type-level methods)。在Swift中,你可以为所有的类、结构体和枚举定义类型方法。每一个类型方法都被它所支持的类型显式包含。

如下例子

class MyTestClass
{

    class func testTypeClassFunc()
    {
        print("这是一个类型方法!")
    }
    static func testSubSuperClassFunc()
    {
        print("这是一个类型方法,子类重写父类方法!")
    }
}

MyTestClass.testTypeClassFunc()
MyTestClass.testSubSuperClassFunc()

运行结果

这是一个类型方法!
这是一个类型方法,子类重写父类方法!
Program ended with exit code: 0
    1. 在类型方法的方法体(body)中,self指向这个类型本身,而不是该类型的某个实例。这意味着我们可以用self来消除类型属性和类型方法参数之间的歧义,类似于上面处理实例属性和实例方法参数时的做法。
    1. 一般来说,在类型方法的方法体中,任何未被限定的方法和属性名称,可以被本类中的其它类型方法和类型属性引用;一个类型方法可以通过类型方法名称直接调用本类中的其它类型方法,不用直接通过类型名来调用;在结构体和枚举中,也能够直接通过类型属性的名称访问本类中的类型属性,而不需要前面加上类型名称。

请看下面的例子

struct LevelTracker
{
    static var highestUnLockLevel = 1//检测玩家已经解锁的最高等级(类型属性)
    var currentLevel = 1//检测每个玩家当前的等级

    static func unlock(_ level:Int)//一旦新等级被解锁,该函数就会更新highestUnLockLevel的值
    {
        if level > highestUnLockLevel
        {
            highestUnLockLevel = level
        }
    }

    /*
     *如果给定Level值<=highestUnLockLevel,说明该等级已经被解锁,就会返回true
     */
    static func isUnlocked(_ level:Int) -> Bool
    {
        return level <= highestUnLockLevel
        //也可以用下面的样式来写
        //return level <= highestUnLockLevel ?true:false
    }

    /*
     *函数被标注为 @ discardableResult,允许在调用函数时候忽略返回值
     *更新currentLevel之前,判断等级是否已经解锁,如果解锁就能设置currentLevel
     */
    @discardableResult
    mutating func advance(to level:Int) -> Bool
    {
        if LevelTracker.isUnlocked(level)
        {
            currentLevel = level
            return true
        }
        else
        {
            return false
        }
    }
}


class Player
{
    var tracker = LevelTracker()
    let playerName:String

    /*complete(level:)
     *一旦玩家完成某个指定等级就会调用它
     *并且为当前所有玩家解锁下一等级,将当前玩家的等级更新为下一级
     */
    func complete(level:Int)
    {
        LevelTracker.unlock(level + 1)
        tracker.advance(to: level + 1)
    }
    init(name:String)
    {
        playerName = name
    }
}

var player = Player.init(name: "TestDemo")
player.complete(level: 1)
print("当前最高等级为:\(LevelTracker.highestUnLockLevel)")

var player2 = Player.init(name: "Hahaha")
if player2.tracker.advance(to: 8)
{
    print("等级解锁成功,玩家当前等级为:\(LevelTracker.highestUnLockLevel)")
}
else
{
    print("等级解锁失败")
}

运行结果

当前最高等级为:2
等级解锁失败
Program ended with exit code: 0

在上面的例子中,

  • LevelTracker是游戏玩家的等级模型,highestUnLockLevel为当前游戏所有玩家中已经解锁的最高等级,currentLevel为每个玩家的当前等级;
  • 一旦新等级被解锁,就会通过unlock(_ level:Int)方法来更新highestUnLockLevel的值;同时会通过isUnlocked(_ level:Int)方法来判断一个给定的等级是否已经被解锁;advance方法的作用请参考注释。
  • Player类为一个游戏玩家模型。当我们试图给player2对象设置一个还未被解锁的等级时,就会提示解锁失败。

相关文章

  • Swift复习系列:方法

    在Swift语言中,方法分两种: 实例方法,为给定类型的实例封装 了具体的任务与功能,通过实例对象来调用; 类型方...

  • Swift复习系列:属性

    先来看一下百度百科关于属性的解释 属性就是对于一个对象的抽象刻画一个具体事物,总是有许许多多的性质与关系,我们把一...

  • Swift复习系列:下标

    在访问Array或Dictionary时,我们除了可以通过系统的标准函数库,还可以使用下面的方式: array[i...

  • Swift复习系列:继承

    一个类可以继承另一个类的属性、方法以及其它特性,继承的类叫子类,被继承的类叫父类(或者 超类)。 在Swift中,...

  • Swift复习系列:集合类型

    在Swift中集合类型有三种Arrays、Dictionarys、Sets三种, 1.Array是有序数据的集,数...

  • Swift复习系列:基础部分

    前言说明 1.Swift是一种类型安全语言,你可以清楚的知道值的类型,当你想传入一个Int类型的数据,类型安全会阻...

  • 访问控制,内存管理

    swift系列课程 访问控制 扩展 将方法赋值给var\let sssimage.png 内存管理

  • swift第一讲

    swift系列课程 编译流程 Swift code --> Swift AST -->Raw Swift IL ...

  • Swift5复习(一)Swift编译流程、基础语法、流程控制、函

    Swift5复习(一)Swift编译流程、基础语法、流程控制、函数、枚举Swift5复习(二)可选项、结构体、类、...

  • Swift5复习(四)继承、初始化、可选链

    Swift5复习(一)Swift编译流程、基础语法、流程控制、函数、枚举Swift5复习(二)可选项、结构体、类、...

网友评论

    本文标题:Swift复习系列:方法

    本文链接:https://www.haomeiwen.com/subject/ckmcsxtx.html