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. CSS3新增的属性有哪些:

    CSS 用于控制网页的样式和布局. CSS3 是最新的 CSS 标准. CSS3新增了很多的属性,下面一起来分析一下新增的一些属性: 1.CSS3边框: border-radius:CSS3圆角边框. ...

  2. HDU-4296 Buildings 贪心 从相邻元素的相对位置开始考虑

    题目链接:https://cn.vjudge.net/problem/HDU-4296 题意 有很多板子,每一个板子有重量(w)和承重(s)能力 现规定一块板子的PDV值为其上所有板子的重量和减去这个 ...

  3. The Zen of Python, by Tim Peters

    Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Comp ...

  4. vue2.0移动端自定义性别选择提示框

    这篇文章主要是简单的实现了vue2.0移动端自定义性别选择的功能,很简单但是经常用到,于是写了一个小小的demo,记录下来. 效果图: 实现代码: <template> <div c ...

  5. 【Hibernate学习】 —— 抓取策略(注解方式)

    当应用程序须要在关联关系间进行导航的时候.hibernate怎样获取关联对象的策略. 抓取策略的方式: FetchType.LAZY:懒载入.载入一个实体时.定义懒载入的属性不会立即从数据库中载入. ...

  6. WIZnet相关产品介绍

    WIZnet  自1998年在韩国创立以来,一致专注研发全硬件TCP/IP协议栈芯片.同一时候开发设计相关网络模块和无线产品,同一时候 WIZnet 鼓舞开源硬件.相关开源硬件产品也已层出不断. 主要 ...

  7. 工作笔记5.JAVA图片验证码

    本文主要内容为:利用JAVA图片制作验证码. 设计思路: 1.拷贝AuthImageServlet.class图片验证码 2.配置web.xml 3.JSP中,调用封装好的AuthImageServl ...

  8. 6、python中的字符串

    最早的编码为ascii码,共256个符号.UTF-8是国际通用编码,全面支持中文,以一个字节表示英文,以三个字节表示一个中文以及其他语言:GB2312是我国自己定制的中文编码标准,使用1个字节表示英文 ...

  9. thinkPHP的模板是做什么用的

    thinkPHP的模板是做什么用的 问题 为什么PHP中ThinkPHP有做类似模板引擎的东西?smarty也是?这些到底有何用? 我是真没发现它们的用处在哪里?分离了前端和PHP的依赖?HTML文件 ...

  10. SparkStreaming基础

    * SparkStreaming基础 打开之前构建好的Maven工程,如何构建?请参看SparkCore基础(二)的最后部分. 在SparkCore中,我们操作的数据都在RDD中,是Spark的一个抽 ...