设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

从Objective-C到Swift—Swift糖果

2014-6-30 14:50| 发布者: joejoe0332| 查看: 5872| 评论: 0|原作者: GoodLoser, chasehong|来自: oschina

摘要: Swift带来很多确实很棒的特性,使得很难再回到Objective-C。主要的特性是安全性,不过这也被看成是一种额外副作用。


对象的生命周期

  另一个类与结构体的不同是类可以被子类化。 雷和结构体都可以被拓展,并且实现protocol,但是只用类可以继承其他类。

01class Pineapple : Apple {
02    init(color: String) {
03        super.init(color)
04    }
05    convenience init() {
06        self.init("green")
07    }
08    convenience init(ripe: Bool) {
09        self.init()
10        if ripe {
11            color = "yellow"
12        else {
13            color = "green"
14        }
15    }
16    deinit {
17        println("Pineapple down")
18    }
19    override func description() -> String {
20        return "pine" + super.description()
21    }
22    override func enripen() {
23        color = "yellow"
24    }
25}

  就像你看到的,Swift为继承添加了一点更有趣的需要学习的东西。对于初学者来说,你需要清除你覆盖父类中某个方法的意图。如果你想阻止子类覆盖一些东西,你可以在一个单独声明或整个类的前面加上@final属性。阅读 Apple’s documentation了解更多。


初始化

  Swift的对象分两步进行初始化: 首先对象必须是有效的,然后它能被替换。

01class ChildShoe {
02    var size: Double // Uninitialized properties are not allowed unless taken care of in init()
03    init(foot_size: Double) {
04        size = foot_size // First make the object valid
05        addGrowthCompensation()
06    }
07    func addGrowthCompensation() {
08        size++
09    }
10}

  使对象有效必须要调用一个超级类指定的init()方法。类可以同时拥有指定的以及便捷的(用关键词'convenience'标记)初始化方法。便捷初始化方法调用同一个类中的其他初始化方法(最终还是一个指定的初始化方法),而指定的初始化方法调用超级类的初始化方法。

  如果你给所有的超级类指定初始化方法添加初始化方法,你的类也会自动继承所有便捷初始化方法。如果没有添加任何指定的初始化方法,你的类则继承超级类的所有(指定的和便捷的)初始化方法。

  深入阅读请参见Initialization


类型转换

  类之间的转换,特别是向下转换,你可以使用"is","as?"和"as"关键词:

01let apple: Apple = Pineapple()
02 
03let exotic: Bool = apple is Pineapple
04 
05let pineappleOption: Pineapple? = apple as? Pineapple
06let pineapple: Pineapple = apple as Pineapple // NOTE: Throws if not!
07 
08if let obj = apple as? Pineapple { // If executed, 'obj' is a Pineapple
09    "sweet"
10}

想了解更多这方面内容请参见Type Casting一章.


泛型

  泛型是Swift的一个加分的特点。他们看起来有一点像C++里面的模板,但是有更强的型别,也更简单(更简单使用,功能稍逊)。

01// Mark both Int and Double as being convertible to a Double using the '+' prefix
02protocol DoubleConvertible {
03    @prefix func +(v: Self) -> Double
04}
05@prefix func +(v: Int) -> Double { return Double(v) }
06extension Double: DoubleConvertible {}
07extension Int: DoubleConvertible {}
08// NOTE: Repeat this for all Int*, UInt*, and the Float type
09 
10// The traits of a generalized point
11protocol PointTraits {
12    typealias T
13    class var dimensions: Int { get }
14    func getCoordinate(dimension: Int) -> T
15}
16 
17// Generalized Pythagoras
18struct Pythagoras<P1: PointTraits, P2: PointTraits where P1.T: DoubleConvertible, P2.T: DoubleConvertible> {
19    static func apply(a: P1, b: P2, dimensions: Int) -> Double {
20        if dimensions == 0 {
21            return 0
22        }
23        let d: Double = +a.getCoordinate(dimensions-1) - +b.getCoordinate(dimensions-1) // NOTE: '+' to convert to Double
24        return d * d + apply(a, b: b, dimensions: dimensions-1)
25    }
26    static func apply(a: P1, b: P2) -> Double {
27        let dimensions = P1.dimensions
28        assert(P2.dimensions == dimensions)
29        return apply(a, b: b, dimensions: dimensions)
30    }
31};
32 
33import func Foundation.sqrt // NOTE: You can import a typealias&shy;, struct&shy;, class&shy;, enum&shy;, protocol&shy;, var&shy;, or func only
34 
35func distance<P1: PointTraits, P2: PointTraits where P1.T: DoubleConvertible, P2.T: DoubleConvertible>(a: P1, b: P2) -> Double {
36    assert(P1.dimensions == P2.dimensions)
37    return sqrt(Pythagoras.apply(a, b: b));
38}
39 
40// A generalized 2D point
41struct Point2D<Number> : PointTraits {
42    static var dimensions: Int { return 2 }
43    var x: Number, y: Number
44    func getCoordinate(dimension: Int) -> Number { return dimension == 0 ? x : y } // NOTE: The typealias T is inferred
45}
46let a = Point2D(x: 1.0, y: 2.0)
47let b = Point2D(x: 5, y: 5)
48Pythagoras.apply(a, b: b) // NOTE: Methods require all argument names, except the first
49distance(a, b) // NOTE: Functions do not require argument names
50 
51// UIColor
52extension UIColor : PointTraits {
53    class var dimensions: Int { return 4 }
54    func getCoordinate(dimension: Int) -> Double {
55        var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0
56        getRed(&red, green: &green, blue: &blue, alpha: &alpha)
57        switch dimension {
58        case 0: return red
59        case 1: return green
60        case 2: return blue
61        defaultreturn alpha
62        }
63    }
64}
65distance(UIColor.redColor(), UIColor.orangeColor())


  以上代码是受Boost中的Design Rationale的启发.几何的C++库。Swift中的泛型功能不是那么强,但是却能使源码比C++中泛型更具阅读性。


  Swift的泛型是通过类型参数化的。每个参数类型要求实现一个特定的协议或者继承自一个特定的基类。在申明参数类型后,有一个可选的"where"项目能用于给这个类型(或者是他们的内部类型,就如上面那个PointTraits协议中的别名'T')添加额外的需求。这个"where“也能要求两种类型是相等的。


  苹果有更多更完整的Generics章节。


选定Swift

  现在你已经准备好了去看各种各样的源码了,甚至可以自己写了 :-)


  在把你自己留在一个新的大的Swift未知大陆之前,我有几个最终的建议:

  • Apple推荐你使用Int作为所有Integer类型,即使你之前用无符号数的地方。“只有在你真的需要一个与平台原生大小想相同的无符号integer类型时再使用UInt类型.”

  • 如果你想知道@private和al.在哪:好吧,他们还没完成呢,后续版本会加进来的。

  • 如果你创建了一个module,你可以Cmd+单击你的module的名字来查看你的module的自动生成的Swift头。

  • Swift的modules其实是命名空间,因此在任何东西前加像 CF, NS, UI等的前缀。当创建第三方库是就不是那么绝对必要了。


Enjoy using Swift!


酷毙

雷人

鲜花

鸡蛋

漂亮
  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部