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. Python内置数据结构之字符串str

    1. 数据结构回顾 所有标准序列操作(索引.切片.乘法.成员资格检查.长度.最小值和最大值)都适用于字符串,但是字符串是不可变序列,因此所有的元素赋值和切片赋值都是非法的. >>> ...

  2. js+css实现全局loading加载

    js var Mask = function() { //定义一个Mask对象 this.btn = ["取消", "确定"], this.init = fun ...

  3. [arc086e]snuke line

    题意: 有n个区间,询问对于$1\leq i\leq m$的每个i,有多少个区间至少包含一个i的倍数? $1\leq N\leq 3\times 10^5$ $1\leq M\leq 10^5$ 题解 ...

  4. MHA搭建及故障维护

    MHA是一种方便简单可靠的MySQL高可用架构,具体的介绍我在这里就不多说了,下面是我在网上找的一个教程,我在此基础上进行了一些修改: 大致步骤 (一).环境介绍 (二).用ssh-keygen实现四 ...

  5. 紫书 例题8-4 UVa 11134(问题分解 + 贪心)

     这道题目可以把问题分解, 因为x坐标和y坐标的答案之间没有联系, 所以可以单独求两个坐标的答案 我一开始想的是按照左区间从小到大, 相同的时候从右区间从小到大排序, 然后WA 去uDebug找了数据 ...

  6. 紫书 例题 11-6 UVa 658 (状态压缩+隐式图搜索+最短路)

    这道题用到了很多知识点, 是一道好题目.      第一用了状态压缩, 因为这里最多只有20位, 所以可以用二进制来储存状态 (要对数据范围敏感), 然后 涉及到了一些位运算.     第二这里是隐式 ...

  7. 如何配置任意目录下Web应用程序

    1,首先创建一个Web项目,tomcat 7, JDK 1.8 2,创建Web项目并部署到tomcat服务器下运行的步骤和方法: 在Eclipse下创建一个JAVA project 在JAVA项目下创 ...

  8. HDU 4069 数独

    好久没做题了,建图搞了好久…… 然后,判是否有多解的时候会把原来的答案覆盖掉…… 这里没注意,弄了一下午…… 代码: #include <iostream> #include <cs ...

  9. servlet3.0 @webfilter 过滤顺序

    Servlet3.0之前Filter过滤的顺序是由用户在web.xml中配置的顺序决定的,如下会先执行encodingFilter,再执行filter1. <filter> <dis ...

  10. NHibernate概括

    什么是?NHibernate?NHibernate是一个面向.NET环境的对象/关系数据库映射工具. 对象/关系数据库映射(object/relational mapping,ORM)这个术语表示一种 ...