Swift-方法(Methods)

      方法是与某些特定类型相关联的函数。类、结构体、枚举都可以定义实例方法;实例方法为给定类型的实例封装了具体的任务与功能。类、结构体、枚举也可以定义类型方法;类型方法与类型本身相关联。类型方法与 Objective-C 中的类方法(class methods)相似。
       结构体和枚举能够定义方法是 Swift 与 C/Objective-C 的主要区别之一。在 Objective-C 中,类是唯一能定义方法的类型。但在 Swift 中,你不仅能选择是否要定义一个类/结构体/枚举,还能灵活的在你创建的类型(类/结构体/枚举)上定义方法。

实例方法

实例方法是属于某个特定类、结构体或者枚举类型实例的方法。实例方法提供访问和修改实例属性的方法或提供与实例目的相关的功能,并以此来支撑实例的功能。实例方法的语法与函数完全一致,实例方法要写在它所属的类型的前后大括号之间。

俗话说得好:失败乃成功之母,失败多了,不断坚持,必然会成功的!首先定义一个People类,包含了相应的属性和方法,每次失败,失败次数加1,调用increment方法,有的时候连续失败好几次,调用incrementBy方法,如果太失败了,那么重新开始,执行reset方法,isEnough重要是看目前失败次数是否已经足够。不足够,那就继续失败吧,足够了,那么成功的日子来啦。

class People{
    var failCount: Int = 0     //失败的次数
    func increment() {         //失败次数加1
        failCount += 1
    }
    func incrementBy(amount: Int){ //有的时候连续失败好几次
        failCount += amount
    }
    func reset(){         //失败的太彻底了,从头开始
        failCount = 0
    }
    func isEnough() -> Bool{  //失败了这么多次,有没有完啊?
        if failCount > 1000{  //都失败了1000次多次了,终于成功了.
            return true
        }else{     //做的还不够!
            return false
        }
    }
}
简单使用一下

func test(){
    //实例化People
    let oldCoder = People()
    //增加失败次数
    for i in 1..<10 {
        oldCoder.incrementBy(amount: i+100)
    }
    //失败次数是否足够了
    if oldCoder.isEnough(){
        print("失败次数也够了啊,是时候叼一次了!嘿嘿!成功吧!")
    }else{
        print("谁让失败是成功它娘啊!继续失败吧!")
    }
}
注意: 
1)实例方法能够访问它所属类型方法和属性.比如上面isEnough()方法就直接访问了存储属性failCount.
2)实例方法只能够被它所属的类的实例调用,且实例方法不能脱离现有实例而被独自调用. 
3)方法也是函数,所以方法也有内部参数名和外部参数名.

self属性

类型的每一个实例都有一个隐含属性叫做self,self完全等同于该实例本身。你可以在一个实例的实例方法中使用这个隐含的self属性来引用当前实例。上面例子中的increment方法还可以这样写:

 func increment() {         //失败次数加1
        self.failCount += 1
 }

实际上,你不必在你的代码里面经常写self。不论何时,只要在一个方法中使用一个已知的属性或者方法名称,如果你没有明确的写self,Swift 假定你是指当前实例的属性或者方法。这种假定在上面的People中已经示范了:People中的三个实例方法中都使用的是failCount(而不是self.failCount)。

使用这条规则的主要场景是实例方法的某个参数名称与实例的某个属性名称相同的时候。在这种情况下,参数名称享有优先权,并且在引用属性时必须使用一种更严格的方式。这时你可以使用self属性来区分参数名称和属性名称。下面的例子中,self消除方法参数x和实例属性x之间的歧义

struct Point {
    var x = 0.0, y = 0.0
    func isToTheRightOfX(x: Double) -> Bool {
        return self.x > x
    }
}

func testPoint(){
    let somePoint = Point(x: 4.0, y: 5.0)
    if somePoint.isToTheRightOfX(x: 1.0) {
        print("This point is to the right of the line where x == 1.0")
    }
    //如果不使用self前缀,Swift 就认为两次使用的x都指的是名称为x的函数参数。
}

在实例方法中修改值类型


结构体和枚举是值类型。一般情况下,值类型的属性不能在它的实例方法中被修改。但是,如果你确实需要在某个具体的方法中修改结构体或者枚举的属性,你可以选择变异(mutating)这个方法,然后方法就可以从方法内部改变它的属性;并且它做的任何改变在方法结束时还会保留在原始结构中。方法还可以给它隐含的self属性赋值一个全新的实例,这个新实例在方法结束后将替换原来的实例。要使用变异方法, 将关键字mutating 放到方法的func关键字之前就可以了:

struct Point {
    var x = 0.0, y = 0.0
    mutating func moveByX(deltaX: Double, y deltaY: Double) {
        x += deltaX
        y += deltaY
    }
}

func testPoint(){
    var somePoint = Point(x: 1.0, y: 1.0)
    somePoint.moveByX(deltaX: 2.0, y: 3.0)
    print("The point is now at (\(somePoint.x), \(somePoint.y))")
    // 打印输出: "The point is now at (3.0, 4.0)"
    
    // let fixedPoint = Point(x: 3.0, y: 3.0)
    // fixedPoint.moveByX(2.0, y: 3.0) //这里将会抛出一个错误,因为要改变,必须使用var,而不能是let
}
上面的Point结构体定义了一个变异方法(mutating method)moveByX(_:y:)用来移动点。moveByX方法在被调用时修改了这个点,而不是返回一个新的点。方法定义时加上mutating关键字,这才让方法可以修改值类型的属性。
注意:不能在结构体类型常量上调用变异方法,因为常量的属性不能被改变,即使想改变的是常量的变量属性也不行.

在变异方法中给self赋值
变异方法能够赋给隐含属性self一个全新的实例。上面Point的例子可以用下面的方式改写:

struct Point {
    var x = 0.0, y = 0.0
    mutating func moveByX(deltaX: Double, y deltaY: Double) {
        self = Point(x: x + deltaX, y: y + deltaY)
    }
}
//枚举的变异方法可以把self设置为相同的枚举类型中不同的成员:
enum TriStateSwitch {
    case off, low, high
    mutating func next() {
        switch self {
        case .off:
            self = .low
        case .low:
            self = .high
        case .high:
            self = .off
        }
    }
}
var ovenLight = TriStateSwitch.low
ovenLight.next()
// ovenLight现在等于.high
ovenLight.next()
// ovenLight 现在等于.Off
上面的例子中定义了一个三态开关的枚举。每次调用next方法时,开关在不同的电源状态(off,low,high)之前循环切换。

类型方法

实例方法是被某个类型的实例调用的方法。你也可以定义在类型本身上调用的方法,这种方法就叫做类型方法。在方法的func关键字之前加上关键字static,来指定类型方法。类还可以用关键字class来允许子类重写父类的方法实现。

注意:在 Objective-C 中,你只能为 Objective-C 的类类型(classes)定义类型方法(type-level methods)。在 Swift 中,你可以为所有的类、结构体和枚举定义类型方法。每一个类型方法都被它所支持的类型显式包含。

类型方法和实例方法一样用点语法调用。但是,你是在类型上调用这个方法,而不是在实例上调用。下面是如何在SomeClass类上调用类型方法的例子:

class SomeClass {
    class func someTypeMethod() {
        // 在这里实现类型方法
    }
}
SomeClass.someTypeMethod()

下面看个例子

class Car{

    //类型属性必须是计算属性
    class var currentEra: String{
        return "第三代油电混合车"
    }
    
    var brand:String = "奔驰"
    //车的历史,属于车这个类的全体,而不是属于哪一个品牌
    class func history(){
        print("第一代是马拉车")
        print("第二代是汽油车")
        print("第三代是油电混合车")
        print("第四代是智能车")
        
        //反问类型属性
        print("当前处于\(currentEra)")
        //print("目前是\(brand)") 这里报错
    }
}

1:对于类型方法,其定义格式为:class func 方法名(参数列表) ->(返回值){方法体}
2:但是对于结构体和枚举类型是: static func 方法名(参数列表) ->(返回值){方法体}
3:在类型方法中,可以调用类型属性和类型方法,但是不能够直接使用实例属性和实例方法.原因是类型方法和类型属性定义那一刻就已经存在,所以它们可以在类型方法里调用类型属性,但是实例方法和属性只有实例存在时才存在,所以不能在类型方法里调用实例属性和方法,该调用规则适用于类,结构体,枚举.

下标方法subscript

下标脚本可以定义在类(Class)、结构体(structure)和枚举(enumeration)这些目标中,可以认为是访问集合(collection),列表(list)或序列(sequence的快捷方式,使用下标脚本的索引设置和获取值,不需要再调用实例的特定的赋值和访问方法。举例来说,用下标脚本访问一个数组(Array)实例中的元素可以这样写 someArray[index] ,访问字典(Dictionary)实例中的元素可以这样写 someDictionary[key]。

//注意:下标方法仅用于实例,并且是地道的实例方法,可以在枚举类型,结构体类型和类类型中定义使用.
/*
 1:下标方法的格式为subscript(参数) -> 返回值{get/set访问器}
 2:下标方法的参数,可以是多个也可以是不定参数,但是注意:参数不能够使用inout修饰符或者默认参数.
 3:在同一个实例中可以存在多个下标方法,编译器根据脚本的参数和返回值决定选用哪一个.
 4:下标方法和计算属性类似,完全支持取值和赋值访问器,也支撑只读控制.
*/

class Assistant{
    var interviewees:[Int: String] = [:]
    var name: String = ""
    
    //标准版本 根据应聘者的 ID,返回姓名
    subscript(number: Int) -> String?{
        get{
            return interviewees[number]
        }
        set(value){ //标准格式下,可以在set后面指定参数
            interviewees[number] = value
        }
    }
    
    //精简版本
//    subscript(number: Int) -> String?{
//        get{
//            return interviewees[number]
//        }
//        set{ //在精简格式下:set后面省略的参数默认为newValue
//            interviewees[number] = newValue
//        }
//    }
    
    //只读
    subscript(number:Int,door: Int)->String?{
         get{
            return interviewees[number]
        }
    }
}

func testSubscript(){
    
      //创建对象,设置相应的属性值
      var assistent = Assistant()
      assistent.name = "Jenny"
        
      assistent[07] = "jack"
      assistent[08] = "justin"
        
      print("07号\(assistent[07]!)参与面试")
      print("08号\(assistent[08]!)做好准备")
      print("07号\(assistent[07]!)由snow面试")
      print("08号\(assistent[08]!)去2号会议室面试")
        
      /*
        打印结果:
        07号jack参与面试
        08号justin做好准备
        07号jack由snow面试
        08号justin去2号会议室面试

        */
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值