Methods (方法)


实例方法(Instance Methods)
我认为看到这里。我们唯能八一八的就是swift的自做主张的行为了,反正它就是会以各种方式帮助我们来完毕让代码看起来非常奇怪的事情。。。

在之前函数那一篇笔记中,我们已经看到过參数的外部名字和内部名字的区分了,当然。在实例方法中,这个事情依旧存在,并且。swift又会帮我们做一些潜规则。

swift在默认的情况下,会为方法的第一个參数仅仅提供函数内部使用的名字,而从第二个參数開始,既能够外部用,也能够内部用(就像我们在函数中见过的  External Parameter 一样):

class MyClass{
     var myNum: Int = 0
     func increaseNum(base: Int, numberOfTimes: Int) {
          myNum += base * numberOfTimes
     }
}

var myClassInstance = MyClass()
myClassInstance.increase(10, numberOfTime: 8)   //第二个參数開始,会自己主动的提供一个外部使用变量名 
(感谢 swift技术交流第一平台(355277)的群友 偏未晚(1027115179) 指出错这里的函数名笔误 )
myClassInstance.increaseNum(10, numberOfTime: 8)
  //第二个參数開始,会自己主动的提供一个外部使用变量名

这就相当于。我们在函数那部分提到的函数想为外部提供一个变量名的话,有两种做法:
1.  func myFunc(value paramA: Int)  {……}    //value是给外部用的名字, paramA是给内部用的
2.  func myFunc(#paramA: Int) {……}     //paramA 既是外部用的,也是内部用的

而在上面的MyClass类的实例方法中。相当于,从第二个參数開始。swift自己主动为我们提供人了”#”的功能。而不须要我们明白的写#
这个默认的行为,有时候是很讨厌的,所以swift依旧提供给我们不给外部提供名字的方法:
class MyClass{
     var myNum: Int = 0
     func increaseNum(base: Int, _ numberOfTimes: Int) {      //注意这一行有一个 “_"
          myNum += base * numberOfTimes
     }

在參数的名字前面加了一个”_”和一个空格,这样,swift便不再会自己主动提供外部使用名字了。

当然。假设我们把”_”这里,换成别的名字,那么就跟之前说的函数是一样的了。


self 属性
每一个实例。都有一个属性用于表示它自己这个实例。这个属性叫做self。
class MyClass{
     var  num: Int = 0
     func setNum(num:Int) {
          self.num = num            //注意这里的self
     }
假设出现这个setNum方法的情况,传入的參数名叫num, 而我们设置的属性也叫num的时候,为了区分,究竟是传入的值还是实例的属性。我们为实例属性前面加了self,表示是这个实例自己的属性。


Mutating方法
以上面说的都是类的情况。那么对于 struct, enum这种值传递类型,却不能使用实例方法来改变属性的值。

struct MyPoint {
     var x = 0, y = 0
     mutating func moveByXY(deltaX: Int, y deltaY: Int) {    //注意这里的mutatingkeyword
          x += deltaX
          y += deltaY
     }
}

var instance = MyPoint()
instance.moveByXY(3, y: 4)
println(“x:\(instance.x)  y:\(instance.y)”)
在struct, enum里使用mutatingkeyword,以达到和class里一样的效果
注意:假设上面的x,和y 不是var,而是let的话,是不能用的,由于我们不能改变一个常量的值。

在Mutating方法中,给self赋值
struct MyPoint {
     var x = 0, y = 0
     mutating func changeSelf(deltaX: Int, y deltaY: Int) {
          self = MyPoint (x: deltaX, y: deltaY)      //注意这里的selfkeyword
     }

var instance = MyPoint()
instance.changeSelf(3, y: 4)
println(“x:\(instance.x)  y:\(instance.y)”)

这样的方式,也相同达到了改变 instance中的x和y的目的,然而,这样的给self赋值的方法。却是生成了一个新的MyPoint的实例(而之前的实例是怎样销毁的。内存怎样释放的。要等到后面讲到内存管理的章节才干说到,这里临时不考虑)

enum MyStateMachine {
     case None, Init, Run, Deinit
     mutating func nextState() {
          switch self {
               case None:
                    self = Init
               case Init:
                    self = Run
               case Run:
                    self = Deinit
               case Deinit:
                    self = None
          }
     }
}

var stateMachine = MyStateMachine.None
stateMachine.nextState()                                        //self变成 Init
println(stateMachine == MyStateMachine.Init)          // true

stateMachine.nextState()                                        //self 变成 Run
println(stateMachine == MyStateMachine.Init)          //true

这就非常有意思了,状态机的状态切换的代码能够直接写在enum的定义中

类型方法
上面提到的方法。都是实例相关的方法,它们都是针对某一个实例进行操作的,而类型方法,是对于这个类型的,事实上这样的方法在上一篇笔记中,类型属性的那部分已经出现过keyword了:static和class。


class MyClass {
     class var computedProperty: Int {          //这是一个类型属性,上一篇笔记中提到的

     }

     class func someMethod() {                    //这才是一个类型方法

     }
}

由于类里面的类型属性只能用于计算。不能保存数据。所以类里的类型方法,临时还不适合写一个能够跑起来的样例,应该结合struct 或者enum,才干够写,还是先看看struct的类型方法吧,enum和struct差点儿相同(这是个官方样例, 方便复制就不帖图了。不过抄了一遍。由于我非常喜欢这个样例,在实际的游戏开发中非经常常使用):

struct LevelTracker {
     static var highestUnlockedLevel = 1                       //类型属性。全部的实例共用这个值
     static func unlockLevel(level: Int) {                         //类型方法
          if level > highestUnlockedLevel {
               highestUnlockedLevel = level
          }
     }

     static func levelIsUnlocked(level: Int) -> Bool {          //类型方法
          return level <= highestUnlockedLevel
     }

     var currentLevel = 1

     mutating func advanceToLevel(level: Int) -> Bool {               //Mutating方法,是个实例方法
          if LevelTracker.levelIsUnlocked(level) {
               currentLevel = level
               return true
          } else {
               return false
          }
     }
}

class Player {
     var tracker = LevelTracker()          //上面定义的结构体的一个实例
     let playerName: String
     func completedLevel( level: Int) {
          LevelTracker.unlockLevel(level + 1)          //调用了上面那个结构体的类型方法
          tracker.advanceToLevel(level + 1)             //调用了tracker这个实例的Mutating方法(实例方法)
     }

     init(name: String) {
          playerName = name                  //关于这个playerName常量初始化问题,在后面的章节会提到
     }
}

var player = Player(name: “World”)
player.completedLevel(1)                    //这个函数调用后 tracker的highestUnlockedLevel 会变成2

println(“highest unlocked  level is now \(LevelTracker.highestUnlockedLevel)”)

var player2 = Player(name: “Kitty”)
if player2.tracker.advanceToLevel(6) {          //检測能否够把player2设置为6级
     println(“player is now on level6")
} else {
     println(“level 6 has not yet been unlocked")
}

执行结果是else中的println被执行。
这个样例,假设上面的内容都看懂了的话,读起来应该非常easy。假设还是不懂,那么请回结合上一篇笔记一起看。

swift 笔记 (十一) —— 方法(类,结构体,枚举)的更多相关文章

  1. C# 类&结构体&枚举

    类: class Lei  //要和static void Main(string[] args)平级: { public int lei_int;  //public是关键字,代表访问权限,这里是公 ...

  2. OC基础--结构体 枚举做类成员属性

    结构体  枚举作类的成员属性: 定义一个学生类 性别 -- 枚举 生日 入学日期  毕业日期  --  结构体 代码示例: 声明文件 Student.h: #import <Foundation ...

  3. .NET 基础一步步一幕幕[方法、结构、枚举]

    方法.结构.枚举 方法: 将一堆代码进行重用的一种机制. 语法: [访问修饰符] 返回类型 <方法名>(参数列表){ 方法主体: } 返回值类型:如果不需要写返回值,写void 方法名:P ...

  4. Golang 笔记 2 函数、结构体、接口、指针

    一.函数 Go中函数是一等(first-class)类型.我们可以把函数当作值来传递和使用.Go中的函数可以返回多个结果.  函数类型字面量由关键字func.由圆括号包裹声明列表.空格以及可以由圆括号 ...

  5. Swift基础(类,结构体,函数)

    import Foundation // 创建一个类 class Student { // 属性(类的属性必须赋初值,如果不赋值,需要写自定义方法) var studentName: String v ...

  6. Swift 数组,字典,结构体,枚举

    1.数组 let types = ["none","warning","error"]//省略类型的数组声明 var menbers = [ ...

  7. swift 类 结构体 作为参数 以及可变参数

    Class class Person{ var age = 22, name = "frank" func growolder() { self.age++ //++ 要跟住 不要 ...

  8. C# 结构体 枚举类型

    注意:枚举类型和结构体都属于值类型. 结构体:就是一个自定义的集合,里面可以放各种类型的元素,用法大体跟集合一样. 一.定义的方法: struct student { public int nianl ...

  9. Bash脚本编程学习笔记07:循环结构体

    本篇中涉及到算术运算,使用了$[]这种我未在官方手册中见到的用法,但是确实可用的,在此前的博文<Bash脚本编程学习笔记03:算术运算>中我有说明不要使用,不过自己忘记了.大家还是尽量使用 ...

随机推荐

  1. vue非空校验

    效果图 实现代码 //页面html <div> <ul class="listinfo"> <li> <span class=" ...

  2. 抓取豆瓣的电影排行榜TOP100

    #!/usr/bin/env python # -*- coding:utf-8 -*- """ 一个简单的Python爬虫, 用于抓取豆瓣电影Top前100的电影的名称 ...

  3. js img图片加载失败,重新加载+断网检查

    我们常常会遇到img加载图片的时候因为网络问题或者图片过大导致图片加载失败的问题,页面就因为这张蹦掉的图变得不美观.所以我们需要图片加载失败的时候重新加载图片,前端图片加载优化 //js方法定义 fu ...

  4. centos7.3安装php7.0

    需求:在Centos7.3下搭建LNMP环境 文章转载自:http://blog.csdn.net/wszll_alex/article/details/76285324 作者:狂热森林 . 关闭防火 ...

  5. Python学习第二天-编写购物车

    需求:1.启动程序后,让用户输入工资,然后打印商品列表         2.允许用户根据商品编号购买商品         3.用户选择商品后,检测余额是否够,够就直接扣款,不够就提醒          ...

  6. [MST] Test mobx-state-tree Models by Recording Snapshots or Patches

    Testing models is straightforward. Especially because MST provides powerful tools to track exactly h ...

  7. nj10---文件读取

    介绍:fs模块是文件操作的封装,它提供了文件的读取,写入,更名,删除,遍历目录,链接POSIX文件系统操作.与其他模块不同的是,fs模块中所有的操作都提供了异步和同步两个版本,例如读取文件内容函数异步 ...

  8. 如何在阿里云服务器里配置iis 搭建web服务

    IIS,互联网信息服务,一种Web服务组件,利用它,我们可以打开asp.php这些搭建网页所用的文件.   工具/原料   域名 服务器 方法/步骤     登录服务器.   点击开始—>服务器 ...

  9. 迷宫求解_数据结构c语言版

    #include <iostream> #include <string> #include <cstdio> #include <cstdlib> # ...

  10. django 笔记9 分页知识整理

    感谢老男孩 自定义分页 XSS:攻击 默认字符串返回 {{page_str|safe}} 前端 from django.utils.safestring import mark_safe page_s ...