数字夜话的博客

开始好好写博客.

Swift 函数与类

上一篇文章,初步了解了swift与xcode 6的内容。下面继续总结swift语法中的函数与类。

函数与闭包 (Functions and Closures)


swift函数定义规则是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
func 函数名(参数名:参数类型,参数名:参数类型,...)-> 返回值类型 {
    //函数主体
    return (a,b,c)
}
//例子
func sumOf(numbers: Int...) -> Int {
    var sum = 0
    for number in numbers {
        sum += number
    }
    return sum
}
sumOf()              // result:0
sumOf(42, 597, 12)   // result:651

/*----------- 返回一个函数名,它也是一个内嵌函数 ------------*/
func 函数名(参数名:参数类型,参数名:参数类型,...)-> (参数类型1 -> 返回类型1) {
    func nestedFunc(参数名:参数类型1)>返回类型1{
         return 返回类型1
    }
    return nestedFunc
}
//例子
func makeIncrementer() -> (Int -> Int) {
    func addOne(number: Int) -> Int {
        return 1 + number
    }
    return addOne
}
var increment = makeIncrementer()
increment(7)  //result: 8

/*----------- 把函数作为函数的一个参数 ------------*/
func 函数名(参数名:参数类型,函数名:参数类型 -> 返回类型) -> 返回类型{

}
//例子,判断是否存在小于10的数字
func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool {
    for item in list {
        if condition(item) {
                return true
        }
    }
    return false
}
func lessThanTen(number: Int) -> Bool {
    return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(numbers, lessThanTen)

* 返回类型支持返回多个值。方法是使用括号括住返回值:(rA,rB,rC)
* 参数列表也支持输入一组有效的参数值,将以数组形式传入函数。
* 内嵌函数函数可以互相嵌套,内部函数可以使用外部函数的值。
* 函数可以作为一个类型被返回。
* 函数可以作为一个参数被传入到另外一个函数。

闭包(Closure)

闭包是一个不显示参数与返回类型的特殊函数,你可以通过闭包来写一个匿名函数,将主体写在{}中,用in区分主体参数值返回类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
    (参数名:参数类型)->返回类型 in
    //closure body
    return 返回类型值
}
// 例子,返回一个包含运行闭包后的结果集合。先看看map的定义:
//—————————————begin—————————————————
/// Return a Array containing the results of calling
/// `transform(x)` on each element `x` of `self`
/// 返回一组(每个子元素都)调用闭包后的结果集合
    func map<U>(transform: (T) -> U) -> U[]
//—————————————end—————————————————

var numbers = [20, 19, 7, 12]
var result  = numbers.map(
{
    (number: Int) -> Int in
    let result = 3 * number
    return result
})
println("\(result)")  // result: [60, 57, 21, 36]

var result = sort([1,5,3,12,2]){$0>$1}      //结果执行过程看下图
println("\(result)"); //result:[12,5,3,2,1]

"工程目录结构"

对象和类(Objects and Classes)

类的定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class classname:inheritType{//:inheritType 是继承对象。在这里是可选值。
//here is your code
  //properties
      var aString : String
    {
////      注意不允许在set方法中对自身值进行赋值,否则将导致死循环。
//        set {//默认传入值用newValue表示,也可以用 set (newname) 来设置一个新值的别名
//            println("set value as \(newValue)") //println("set value as \(newname)")
//        }
//
//        get {
//            return self.aString
//        }

////   注意,set get必须同时存在,否则编译器报错。
////        willSetdidSet必须同时存在。
////        setgetwillSetdidSet不能同时存在
        willSet (anewvalue){ //这里使用了新值的别名anewvalue,默认为newValue
            println("self.aString:\(self.aString) set as newValue:\(anewvalue)");
        }
        didSet {
            println("after set \(self.aString)");
        }
    }
        // methodes
  init(){ //构造方法,若不添加编译器将会报错。
      super.init();//调用父类的构造方法。注意:这里必须顺序,先初始化父类构造方法,子类才能调用父类属性与方法。
      self.aString = aStr;
  }
  deinit{//析构方法,可选方法:此方法不需要参数

      }
/*
 override func aFuncInInheritType(){//父类方法重写.若需要重写父类方法,可以使用override关键字

  }

*
}

var aclass:MyClass = MyClass(aStr:"hello”);//此处willSet和didSet方法不执行。只执行了set和get方法
    aclass.aString = "hello,word;//此处执行willSetdidSet。说明willSetdidSet在初始化时不调用,setget方法每次对其进行赋值,都会被调用。

处理变量的可选值时,你可以在操作(比如方法、属性和子脚本)之前加?。如果?之前的 值是 nil,?后面的东西都会被忽略,并且整个表达式返回 nil。否则,?之后的东西都会被运行。

枚举与结构体(Enumerations and Structures)

枚举用enum来定义:enum 枚举名:枚举类型{枚举体},枚举类型可选。例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//定义扑克的AK,数值从1开始增加,且定义一个simpleDescription函数,用于输出切换数值和名称。
enum Rank: Int { //若去掉:Int 则不允许赋值Ace = 1
        case Ace = 1
        case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
        case Jack, Queen, King
        func simpleDescription() -> String {
            switch self {
            case Rank.Ace:
                return "ace"
            case Rank.Jack:
                return "jack"
            case .Queen:            //可用`.Queen`表示Rank.Queen
                return "queen"
            case .King:
                return "king"
            default:
                return String(self.toRaw())
            }
        }
    }
let queen = Rank.Queen            //枚举一个ace
let queenRawValue = queen.toRaw()          //切换为数值,result:12
var des = queen.simpleDescription()      //输出枚举字符描述,result:ace
if let convertedRank = Rank.fromRaw(queenRawValue) { //12转换为枚举类型,等价于Rank.Queen
            let threeDescription = convertedRank.simpleDescription()
            println("\(threeDescription)")
        }

toRaw()转换为数值,fromRaw(avalue)将avalue转换为枚举型。

接口与扩展(Protocols and Extensions)

swift中同样用protocol来声明接口,类、枚举和结构体都可以实现接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
protocol ExampleProtocol {
    var simpleDescription: String { get }
    mutating func adjust()
}
class SimpleClass: ExampleProtocol {
    var simpleDescription: String = "A very simple class."
    var anotherProperty: Int = 69105
    func adjust() {
        simpleDescription += "  Now 100% adjusted."
    }
}

struct SimpleStructure: ExampleProtocol {
    var simpleDescription: String = "A simple structure"
    mutating func adjust() {
        simpleDescription += " (adjusted)"
    }
}

mutating 用于修饰一个可被修改的函数体。当接口被类继承时,不需要用mutating 来重写方法体,当接口被枚举和结构体的使用,使用mutating关键字来重新修改结构体。

1
2
3
4
5
6
7
8
9
10
11
12
13
extension Int{
    func descript()->String{
        return "int value is:\(self)";
    }
}
extension Int: ExampleProtocol {
    var simpleDescription: String {
    return "The number \(self)"
    }
    mutating func adjust() {
        self += 42
    }
}

使用extension为某个类型扩展变量或者方法。当运行时赋值对象与定义变量类型不符时,只实现变量类型的那部分实现。例如:

1
2
3
4
5
var simpleClassA: SimpleClass = SimpleClass();
simpleClassA.adjust();
let protocolValue: ExampleProtocol = simpleClassA;  //simpleClass类赋值给protocolValueprotocolValue为接口类型时,编译器只将SimpleClass实现ExampleProtocol 赋值给protocolValue,所以你不能通过protocolValue调用simpleclassA的属性或方法。
protocolValue.simpleDescription
// protocolValue.anotherProperty  // Uncomment to see the error

泛型(Generics)

在尖括号里写一个名字来创建一个泛型函数或者类型。泛型类型可以在函数和方法中使用,也可以在类,枚举和结构体使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//函数定义的乏型
func funcGenerics<T>(item:T) -> T[]{ //为方法定义泛型T,T的类型是参数的格式(由参数判定),返回是参数格式的数组
    var a = T[]();
    a += item;
    return a;
}
let fg = funcGenerics(hello);//返回一个String类型数组
let fg2= funcGenerics(3.141592628);//返回一个Double型数组。

//类泛型
class classGenerics<T> {
    func method(a:T){
        println(a);
    }
}
var gClass = classGenerics<String>();
    gClass.method("aString");
//或者-----Double类型
var gClass = classGenerics<Double>();
    gClass.method(3.1415926);

//枚举泛型
enum enumGenerics<T>{
        case a;
        case b(T);
        mutating func description(){
            switch self {
                case a:println( "result is none");
                case b(var val):println("result in b(T) is:\(val)”)//定义一个val变狼,类型为T
            }
        }
    }
var eg = enumGenerics<Int>.b(13);
    eg.description();
var eg = enumGenerics<String>.b("a string in enum Generics");
    eg.description();


//结构泛型
struct StructGenerics<T>{
     typealias ItemType = T //定义一个T类型别名。
     mutating func adjust(a: ItemType) {
 println(a);
     }
}
var sg = StructGenerics<Int>();
    sg.adjust(34);
var sg = StructGenerics<String>();
    sg.adjust("struct result is 34");

在类型名后面使用 where 来指定一个需求列表——例如,要限定实现一个协议的类型,需要限定两个类型要相同,或者限定一个类必须有一个特定的父类。

1
2
3
4
5
6
7
8
9
10
11
func anyCommonElements <T, U where T: Sequence, U: Sequence, T.GeneratorType.Element: Equatable, T.GeneratorType.Element == U.GeneratorType.Element> (lhs: T, rhs: U) -> Bool {
    for lhsItem in lhs {
        for rhsItem in rhs {
            if lhsItem == rhsItem {
                return true
            }
        }
    }
    return false
}
anyCommonElements([1, 2, 3], [3])