Swift教程_零基础学习Swift完整实例(三)_swift基础(对象和类、枚举和结构、协议和扩展、泛型)

简介:

4.对象和类(Objects and Classes)

1.同Java一致,使用class和类名来创建一个类。

2.使用init创建一个构造方法,使用deinit创建一个析构方法,通过构造方法来初始化类实例。创建类实例同java一致,在类名后面加上()(实际是调用无参数的构造方法init(),构造方法也可以带参数)。使用.来访问实例的属性和方法。

[objc]  view plain  copy
  1. class NamedShape {  
  2.     var numberOfSides: Int = 0//每个属性都需要初始化一个值——无论是通过声明(就像numberOfSides)还是通过构造器(就像name)。  
  3.     var name: String  
  4.     init(name: String) {  
  5.         self.name = name//self同java中的self,隐示参数,表示类实例  
  6.     }  
  7.     func simpleDescription() -> String {  
  8.         return "A shape with \(numberOfSides) \(name) sides."  
  9.     }  
  10. }  
  11. var namedShape = NamedShape(name: "popkidorc")  
  12. namedShape.simpleDescription()//A shape with 0 popkidorc sides.  

3.子类的定义方法是在它们的类名后面加上父类的名字,用:分割。创建类的时候可以忽略父类。子类如果要重写父类的方法的话,需要用override标记(与java不同,若没有添加override就重写父类方法的话编译器会报错,编译器同样会检测override标记的方法是否确实在父类中)。

[objc]  view plain  copy
  1. class Square: NamedShape {  
  2.     var sideLength: Double  
  3.     init(sideLength: Double, name: String) {  
  4.         self.sideLength = sideLength  
  5.         super.init(name: name)  
  6.         numberOfSides = 4  
  7.     }  
  8.     func area() ->  Double {  
  9.         return sideLength * sideLength  
  10.     }  
  11.     override func simpleDescription() -> String {  
  12.         return "A square with sides of length \(sideLength)."  
  13.     }  
  14. }  
  15. let test = Square(sideLength: 5.2, name"my test square")  
  16. test.area()//27.04  
  17. test.simpleDescription()//A square with sides of length 5.2.  

4.类的属性可以有getter和setter,如果不需要计算属性,但要在设置一个新值之前或之后运行一些代码,使用willSetdidSet

[objc]  view plain  copy
  1. class EquilateralTriangle: NamedShape {  
  2.     var sideLength: Double = 0.0  
  3.     init(sideLength: Double, name: String) {  
  4.         self.sideLength = sideLength//设置子类声明的属性值  
  5.         self.area = sideLength*1.732/2  
  6.         super.init(name: name)//调用父类的构造器  
  7.         numberOfSides = 3//改变父类定义的属性值。  
  8.         //其他的工作比如调用方法、getters和setters也可以在这里执行。  
  9.     }  
  10.     var perimeter: Double {  
  11.         get {  
  12.             return 3.0 * sideLength  
  13.         }  
  14.         set {  
  15.             sideLength = newValue / 3.0//新值的名字是newValue  
  16.         }  
  17.     }  
  18.     var area: Double {  
  19.         willSet{  
  20.             println("an new value \(newValue)")  
  21.         }  
  22.     }  
  23.     override func simpleDescription() -> String {  
  24.         return "An equilateral triagle with sides of length \(sideLength)."  
  25.     }  
  26. }  
  27. var triangle = EquilateralTriangle(sideLength: 3.1, name"a triangle")  
  28. triangle.perimeter//9.3  
  29. triangle.perimeter = 9.9  
  30. triangle.sideLength//3.3  
  31. triangle.perimeter//9.9  
  32. triangle.area//2.6846  

 
  

5.方法的参数名除了第一个外,都需要在调用的时候显式说明。方法的参数名默认和它在方法内部的名字一样,也可以定义另一个名字,在方法内部使用。

[objc]  view plain  copy
  1. class Counter {  
  2.     var count: Int = 0  
  3.     func incrementBy(amount: Int, numberOfTimes times: Int) {  
  4.         count += amount * times  
  5.     }  
  6. }  
  7. var counter = Counter()  
  8. counter.incrementBy(2, numberOfTimes7)//14  

6.操作可选值变量时,可以再在操作(比如方法、属性和子脚本)之前加?。如果?之前的值是nil,?后面的东西都会被忽略,并且整个表达式返回nil。否则,?之后的东西都会被运行。在这两种情况下,整个表达式的值也是一个可选值。

[objc]  view plain  copy
  1. let optionalSquare: Square? = Square(sideLength: 2.5, name"optional square")  
  2. let sideLength = optionalSquare?.sideLength//操作前加?  

5.枚举和结构(Enumerations and Structures)

1.使用enum来创建一个枚举。和类一样,枚举可以包含方法。使用case声明枚举成员。

2.枚举的成员还可以设置默认值(当然可以不用设置,默认从0开始的整数,0、1、2),我们叫原始值,这些值的类型是相同的,并且设置了为第一个成员的原始值后,剩下成员的原始值会按照顺序赋值。通过toRaw方法获取成员的原始值,fromRaw方法尝试通过原始找到枚举成员(若找不到则为nil)。

[objc]  view plain  copy
  1. enum Rank: Int {  
  2.     case Ace = 1  
  3.     case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten  
  4.     case Jack, Queen, King  
  5.     func simpleDescription() -> String {  
  6.         switch self {  
  7.         case .Ace://枚举成员使用缩写.Ace来引用,因为已经知道self的值是一个Rank。已知变量类型的情况下可以使用缩写。  
  8.             return "ace"  
  9.         case .Jack:  
  10.             return "jack"  
  11.         case .Queen:  
  12.             return "queen"  
  13.         case .King:  
  14.             return "king"  
  15.         default:  
  16.             return String(self.toRaw())  
  17.         }  
  18.     }  
  19. }  
  20. let ace = Rank.Ace//枚举成员Rank.Ace需要用全名来引用,因为常量ace没有显式指定类型。  
  21. let aceRawValue = ace.toRaw()//1  
  22. if let convertedRank = Rank.fromRaw(1) {  
  23.     let threeDescription = convertedRank.simpleDescription()//ace  
  24. }  

3.使用struct来创建一个结构。结构和类有很多相同的地方,比如方法和构造器。它们之间最大的区别就是结构是传值,类是传引用。

[objc]  view plain  copy
  1. struct Card {  
  2.     var rank: Rank  
  3.     func simpleDescription() -> String {  
  4.         return "The \(rank.simpleDescription())"  
  5.     }  
  6. }  
  7. let threeOfSpades = Card(rank: .Three)  
  8. let threeOfSpadesDescription = threeOfSpades.simpleDescription()//The 3  

4.一个枚举的成员可以有实例值(也可以叫关联值)。相同枚举成员的实例值可能不同,创建枚举实例的时候传入。而在定义枚举时候设置的原始值对于所有实例都是相同的。

[objc]  view plain  copy
  1. enum ServerResponse {  
  2.     case Result(String, String)  
  3.     case Error(String)  
  4. }  
  5.   
  6. let success = ServerResponse.Result("6:00 am""8:09 pm")//实例值  
  7. let failure = ServerResponse.Error("Out of cheese.")  
  8.   
  9. switch success {  
  10. case let .Result(sunrise, sunset):  
  11.     let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)."//Sunrise is at 6:00 am and sunset is at 8:09 pm.  
  12. case let .Error(error):  
  13.     let serverResponse = "Failure...  \(error)"  
  14. }  

6.协议和扩展(Protocols and Extensions)

1.使用protocol来声明一个协议,类似于java中的接口,为了和interface做为区别我们叫做协议。类、枚举和结构都可以实现协议(发现枚举实现协议协议中好像不能带有属性,希望大神指教)。

[objc]  view plain  copy
  1. protocol ExampleProtocol {  
  2.     var simpleDescription: String { get }//在属性声明后写上{ get set }表示属性为可读写的。{ get }表示属性为可读的。即使为可读的属性实现了setter方法,它也不会出错。  
  3.     mutating func adjust()//mutating关键字用来标记一个会修改结构体的方法  
  4. }  
  5. class SimpleClass: ExampleProtocol {  
  6.     var simpleDescription: String = "A very simple class."  
  7.     var anotherProperty: Int = 69105  
  8.     func adjust() {//不用mutating标记,因为class中的方法经常会修改类  
  9.         simpleDescription += "  Now 100% adjusted."  
  10.     }  
  11. }  
  12. var a = SimpleClass()  
  13. a.adjust()  
  14. let aDescription = a.simpleDescription//A very simple class.  Now 100% adjusted.  
  15.   
  16. struct SimpleStructure: ExampleProtocol {  
  17.     var simpleDescription: String = "A simple structure"  
  18.     mutating func adjust() {  
  19.         simpleDescription += " (adjusted)"  
  20.     }  
  21. }  
  22. var b = SimpleStructure()  
  23. b.adjust()  
  24. let bDescription = b.simpleDescription//A simple structure (adjusted)  

2.使用extension来为现有的类型添加功能(称作扩展),比如添加一个计算属性的方法。可以使用扩展来给任意类型添加协议,甚至是你从外部库或者框架中导入的类型。

[objc]  view plain  copy
  1. extension Int: ExampleProtocol {  
  2.     var simpleDescription: String {  
  3.         return "The number \(self)"  
  4.     }  
  5.     mutating func adjust() {  
  6.         self += 42  
  7.     }  
  8. }  
  9. var i = 7;  
  10. i.adjust()//直接写7.adjust()会有异常,这是因为7是常量,而adjust是mutating改变类方法  
  11. i.simpleDescription//The number 49  
  12. i//49  

3.可以像使用其他命名类型一样使用协议名,可以创建一个有不同类型,但是都实现一个协议的对象集合。当处理类型是协议的值时,协议外定义的方法不可用。

[objc]  view plain  copy
  1. let protocolValue: ExampleProtocol = a  
  2. protocolValue.simpleDescription  
  3. // protocolValue.anotherProperty  // Uncomment to see the error  

7.泛型(Generics)

1.在<>里写一个名字来创建一个泛型方法或者类型。 也可以创建泛型类、枚举和结构体。

[objc]  view plain  copy
  1. func repeat<T>(item: T, times: Int) -> [T] {  
  2.     var result = [T]()  
  3.     for i in 0..<times {  
  4.         result.append(item)  
  5.     }  
  6.     return result  
  7. }  
  8. repeat("knock"4)//["knock", "knock", "knock", "knock"]  

2.在类型名后面使用where来指定一个需求列表,例如要限定实现一个协议的类型,需要限定两个类型要相同,或者限定一个类必须有一个特定的父类。简单起见,可以忽略where,只在冒号后面写接口或者类名。<T: Equatable><T where T: Equatable>是等价的。

[objc]  view plain  copy
  1. func anyCommonElements <T, U where T: SequenceType, U: SequenceType, T.Generator.Element: Equatable, T.Generator.Element == U.Generator.Element> (lhs: T, rhs: U) -> Bool {//限定SequenceType类型,并且Element实现Equatable协议,该协议要求任何遵循的类型实现等式符(==)和不等符(!=)对任何两个该类型进行比较。  
  2.     for lhsItem in lhs {  
  3.         for rhsItem in rhs {  
  4.             if lhsItem == rhsItem {  
  5.                 return true  
  6.             }  
  7.         }  
  8.     }  
  9.     return false  
  10. }  
  11. anyCommonElements([12, 3], [3,4])//true  
  12.   
  13. func anyCommonElementsNew <T, U, R where T: SequenceType, U: SequenceType, T.Generator.Element: Equatable, T.Generator.Element == U.Generator.Element, R == T.Generator.Element> (lhs: T, rhs: U) -> [R] {//限定序列SequenceType类型,并且Element实现Equatable协议,该协议要求任何遵循的类型实现等式符(==)和不等符(!=)对任何两个该类型进行比较。  
  14.     var results = [R]()  
  15.     for lhsItem in lhs {  
  16.         for rhsItem in rhs {  
  17.             if lhsItem == rhsItem {  
  18.                 results.append(lhsItem)  
  19.             }  
  20.         }  
  21.     }  
  22.     return results  
  23. }  
  24. anyCommonElementsNew(["1""2""3""4"], ["3","4","6"])//["3", "4"]  

原文地址:http://blog.csdn.net/ooppookid/article/details/40345557

相关文章
|
3月前
|
存储 安全 Swift
Swift 语言:什么是 Swift 的泛型(Generics)?
Swift 语言:什么是 Swift 的泛型(Generics)?
35 0
|
6月前
|
存储 Swift iOS开发
31 Swift 继续聊聊协议扩展
Swift 继续聊聊协议扩展
49 0
|
4月前
|
Swift
Swift 的控制流结构
Swift 的控制流结构
23 1
|
4月前
|
Swift
Swift 中的枚举(Enum)
Swift 中的枚举(Enum)
24 2
|
4月前
|
存储 数据处理 Swift
在Swift中,类(class)和结构体(struct)
在Swift中,类(class)和结构体(struct)
29 1
|
4月前
|
IDE 开发工具 Swift
Swift语言的教程
Swift语言的教程
48 1
|
6月前
|
Swift C++ 索引
33 Swift泛型的发展历史与泛型的概述
Swift泛型的发展历史与泛型的概述
31 0
|
6月前
|
存储 安全 Swift
29 Swift如何进行类的初始化和反初始化
Swift如何进行类的初始化和反初始化
34 0
|
Swift
Swift - 如何判断一个对象是否是某个类
Swift - 如何判断一个对象是否是某个类
70 0
|
Swift
Swift之UIView的扩展
Swift之UIView的扩展
138 0
Swift之UIView的扩展