发布于 2014-10-27 01:56:45 | 99 次阅读 | 评论: 0 | 来源: 网友投递

这里有新鲜出炉的Swift教程,程序狗速度看过来!

Swift编程语言

SWIFT,苹果于2014年WWDC(苹果开发者大会)发布的新开发语言,可与Objective-C*共同运行于Mac OS和iOS平台,用于搭建基于苹果平台的应用程序。


本文为大家讲解的是如何在Swift中自定义下标(Subscripts)方法,感兴趣的同学可以参考下。

通常情况下,我们在使用数组(Array)或字典(Dictionary)时会使用到下标。其实在Swift中,我们还可以给类(class)自定义下标,下面就让我们来看看Swift中是如何自定义下标的。

通过Subscript赋值和获取值

我们先看看下面这个类:

 
 
class DailyMeal
{
    enum MealTime
    {
        case Breakfast
        case Lunch
        case Dinner
    }
    
    var meals: [MealTime : String] = [:]
}
我们使用该类时可以直接用meals字典,以枚举作为key来查询,像这样:
 
 
var monday = DailyMeal()
 
monday.meals[.Breakfast] = "Toast"
 
if let someMeal = monday.meals[.Breakfast]
{
    println(someMeal)
}
到目前呢,我们创建了DailyMeal类的实例变量monday,并可以使用DailyMeal类中的meals字典进行查询。但是大家有没有感觉monday.meals[]这种写法很累赘呢?至少我看meals就很不顺眼,有没有更简单快捷的方法让我们直接使用monday变量就能赋值或获取Breakfast的值呢?别着急,今天的主角要登场了,让我们先在DailyMeal类中添加如下代码:
 
 
subscript(requestedMeal : MealTime) -> String?
{
    get
    {
        return meals[requestedMeal]
    }
    set(newMealName)
    {
        meals[requestedMeal] = newMealName
    }
}
上面的代码就是一个自定义下标,看起来是不是有点像计算类属性的getter、setter方法的写法呢?但是它们还是有区别的,首先下标使用subscript关键字,然后跟一个圆括号,里面是该下标的参数和参数类型(在实际使用中该参数就相当于数组的index和字典的key一样),最后有该下标的返回值类型。
 
从上面代码可以看到,在下标的getter和setter方法中,其实还是在对meals数组进行操作,但是我们通过下标就可以将对meals数组的操作屏蔽掉。现在来看看我们应该怎样使用:
 
 
var monday = DailyMeal()
 
monday[.Breakfast] = "Toast"
 
if let someMeal = monday[.Breakfast]
{
    println(someMeal) // Toast
}
现在是不是已经没有碍眼的meals了呢,使用起来更加简洁,语义也更加明确了呢,这就是下标最简单的一个用法。
 
如果上面的代码中我们不给monday[.Breakfast]赋值,直接输出值会得到什么结果呢?细心的同学可能会注意到,在定义下标时它的返回值是Optional类型的,所以不赋值直接输出的结果是nil,这样就显得太没礼貌了,所以我们再来改造一下下标的代码:
 
 
subscript(requestedMeal : MealTime) -> String
{
    get
    {
        if let thisMeal = meals[requestedMeal]
        {
            return thisMeal
        }
        else
        {
            return "Ramen"
        }
    }
    set(newMealName)
    {
        meals[requestedMeal] = newMealName
    }
}
我们看到下标的返回值从String?改为了String,那么相应的我们要在getter方法中对meals[requestedMeal]的值进行判断,如果没有赋值的话,我们将返回一个默认值Ramen(兰州拉面让人欲罢不能)。现在我们就可以这样用啦:
 
var monday = DailyMeal()
 
monday[.Lunch] = "Pizza"
 
println(monday[.Lunch])         //Output:  "Pizza"
 
println(monday[.Dinner])        //Output:  "Ramen"
现在使用DailyMeal类是不是感觉到很简介,语义很明确也很健壮呢,答案是肯定的。我们通过下标避免向用户暴露不必要的API,同时也达到了高维护性的目的。
 
DailyMeal类的完整代码如下:
 
 
class DailyMeal
{
    enum MealTime
    {
        case Breakfast
        case Lunch
        case Dinner
    }
 
    var meals: [MealTime : String] = [:]    
    
    subscript(requestedMeal : MealTime) -> String
    {
        get
        {
            if let thisMeal = meals[requestedMeal]
            {
                return thisMeal
            }
            else
            {
                return "Ramen"
            }
        }
        set(newMealName)
        {
            meals[requestedMeal] = newMealName
        }
    }
}
只读下标
 
何为只读下标,顾名思义就是不能通过下标赋值,只能通过下标查询。这种下标的应用场景一般是实现一些数据公式、数据函数,它们一般都是只需要你指定一个数字,然后返回该公式对该数字的计算结果。下面我们用一个阶乘的例子来说明只读下标:
 
 
struct FactorialGenerator
{
    subscript(n: Int) -> Int
    {
        var result = 1
        
        if n > 0
        {
            for value in 1...n
            {
                result *= value
            }
        }
            
        return result
    }
}
同学们可能已经注意到了,上面的下标并没有getter和setter方法。这是因为,如果你想定义一个只读的下标,那么可以不实现setter方法,并且可以省略getter方法的get关键字。Swfit的编译器会判断出这是一个只读的下标,如果你强行通过下标赋值,那么编译器会报错。
 
让我们来使用以下这个阶乘结构体:
 
 
C++
 
 
let factorial = FactorialGenerator()
 
println("Five factorial is equal to (factorial[5]).")
//Output:  "Five factorial is equal to 120."
 
println("Ten Factorial is equal to (factorial[10]).")
//Output:  "Ten Factorial is equal to 3628800."

当然上面这个示例只是展示了只读下标的语法和应用场景,阶乘的实现逻辑在这就不累赘了。总的来说,我们可以通过下标简化暴露给用户的API,你可以在用户毫不知情的情况下更改某个API的功能。不仅使代码更易读,同时也大大提高了代码的可维护性,是不是很酷呢!



最新网友评论  共有(0)条评论 发布评论 返回顶部

Copyright © 2007-2017 PHPERZ.COM All Rights Reserved   冀ICP备14009818号  版权声明  广告服务