前言
上一篇是Swift的一些简单语法,这篇也继续写基本的语法,正所谓,“磨刀不误砍材工”,有兴趣的可以看一下上一篇文章:Swift学习笔记——(一)。
这里主要写一下在Swift中如何定义类和对类的一些操作,另外还有观察属性、可选性以及枚举类型进行了简单的整理。
类和对象
首先,声明一个类:
class MyClass { var className = "hello"; var classAge = 18; func classStart() -> String { return "This class has created!"; } }
接着,创建一个类的实例并使用:
// 创建实例 var myClass = MyClass(); print(myClass.className); // "hello" // 修改变量 myClass.className = "world"; print(myClass.className); // "world" // 调用方法 myClass.classStart();
类的init方法
在类中可以定义一个初始化方法init
,在被实例化的时候调用,如果想现在开始的时候做一些事,在这里好似最合适不过的了。class MyClass { var className = "swift-1"; init() { className = "init"; // 也可以使用self // self.className = "init"; print("hello \(className)"); } } var myClass = MyClass(); // "hello init"
子类可以继承父类
swift中继承使用
class a: A
表示a继承A,重写方法使用override
:// 父类People class People { func say() -> String { return "I am parent's say"; } func read() -> String { return "I am parent's read"; } } // 子类Child继承父类People class Child: People { // 重写父类的方法 override func say() -> String { return "I am child's say"; } } var child = Child(); var sayMsg = child.say(); var readMsg = child.read(); print("say:" + sayMsg); // "say:I am child's say" print("read:" + readMsg); // "read:I am parent's read"
每一个属性都有一个
get
和set
方法用来获取属性和设置属性的值:class People { var firstName = "Tom"; } class Child: People { var name: String { // name属性的get方法 get { return firstName; } // name属性的set方法 set { firstName = newValue + " James"; // newValue:表示给name属性赋的值 } } } var child = Child(); var childName = child.name; // 这时候调用用了get方法获取到name print(childName); // "Tom" child.name = "Jack"; // 这时候调用了set方法,即newValue的值为"Jack" childName = child.name; // 这时候由于上一步的set方法改变了name,所以每次获取属性值时重新调用get方法 print(childName); // "Jack James"
当然,可能觉得
newValue
直接使用不是很舒服,可以显示的传如一个参数,上面的例子可以写成这样:// ... set(value) { firstName = value + " James"; } // ...
属性观察
我们可能有时候想要知道属性的变化,并且在变化之前或者之后做一些事,这时候就要使用willSet
和didSet
,分别是在属性改变之前和改变之后执行的方法。class Child { init() { name = "Tom"; } var name: String { willSet(value) { print("当先的值为:" + name); // "Tom" print("即将变成的值为:" + value); // "James" } didSet(value) { print("当先的值为:" + name); // "James" print("改变之前的值为:" + value); // "Tom" } } } var child = Child(); child.name = "James";
当然,跟
get
和set
一样,可以显示的传递参数,如果不显示传递的,默认为newValue
和oldValue
:// ... willSet { print("即将变成的值为:" + newValue); } didSet { print("改变之前的值为:" + oldValue); } // ...
可选型
在Swift中有一种特殊的类型,叫做可选型。在其他语言中在声明一个变量的时候可以赋为空值,比如说null
,但是在Swift中叫做nil
,使用也是有区别的,在Swift中如果要设置为nil
要这样写:var name: String? = nil; var age: Int = nil; // "报错"
上面的
String?
表示name
既可以是字符串类型也可以是nil
,所以叫做可选型。String
和String?
是两种不同的类型。可选型是不能直接使用的,使用的时候要先进行
unwrapped
,否则会报错,例如:var name1: String? = "Tom"; var name2 = name1 + " James"; // "报错"
这个时候如果我们打印出name1就会发现,name1是这样的:
所以我们需要进行unwrapped
,可以是这样的:var name1: String? = "Tom"; if let name = name1 { // 进行解析可选型,如果不是nil那么就将让name等于实际的字符串 print(name + " James"); // "Tom James" } else { // 可选型为nil print("unwrapped fail"); }
当然Swift还提供了另一种符号,就是
!
,是可以强行拿到可选型实际的值,但是如果值为nil
就会发生错误。var name1: String? = "Tom"; print(name1! + " James"); var name2: String? = nil; print(name2! + " Jack"); // "报错"
当我们想获取可选型的值时,如果不是
nil
,给一个默认值;如果不是nil
那就取可选型解包后的值,可以这样写:// 假设name1是一个可选型(String?) var name2 = name1 ?? "DefaultName"; /* 也可以使用三木运算符 */ var name3 = name1 != nil ? name1 : "DefaultName";
有时候也可以不使用
if
进行解包,比如这样:var str1: String? = "my str"; var STR = str1?.uppercased(); print(STR); // Optional("MY STR")
从上面的例子可以看出,可选型是可以进行链式操作的;并且,从得到的结果发现,对可选型就行解包之后调用函数得到的还是可选性,如果相对
STR
进行进一步操作的话,还是可以使用之前的if
语句。枚举类型
枚举类型是Swift中的一种数据类型,用enum
声明,例如:enum Color { case red case yellow case blue }
当然也可以给定
case
的类型,或者给初始值,就像这样:enum Color: Int { case red = 1 case yellow case blue }
可以简写为:
enum Color: Int { case red, yellow, blue }
使用类型的时候:
enum Color: Int { case red = 1 case yellow case blue } var red: Color = Color.red; print(red); // "red"
如果要去
red
对应的数值,使用rawValue
:enum Color: Int { case red = 1 case yellow case blue } var red: Color = .red; // 此处可以简写为.red print(red.rawValue); // 1 var blue: Color = .blue; print(blue.rawValue); // 3
注:
这里并没有给blue
赋初始值,因为red
为1,Swift自动给下面的case
依次加1,所以blue
为3。
如果都不给初值,第一个也就是red
默认为0,之后依次累加。enum Color: Int { case red case yellow case blue } var blue: Color = .blue; print(blue.rawValue); // 2
同理,如果是
String
类型,那么默认值就是字符串:enum Color: String { case red case yellow case blue } var blue: Color = .blue; print(blue.rawValue); // "blue"
如果知道了
rawValue
的值,如何知道是哪个case
呢?方法是这样的:enum Color: Int { case red = 1 case yellow case blue } if let blue = Color(rawValue: 3) { print("case的值是:" + blue); // "case的值是:blue" } else { print("fail"); }
这里通过
rawValue
获得值是一个可选型,因为如果这个rawValue
可能是枚举类型中不存在的,所以,在上面的例子中,如果Color(rawValue: 4)
,那么得到的是nil
,打印的应该是"fail"
。如果不想给
case
一个初始值,可以定义一个关联值(associated values),可以在后续进行赋值,就像这样:enum People { case name(String) case age(Int) } func getName( username: String) -> People { return .name(username); } var userInfo = getName(username: "Tom James"); switch userInfo { case let .name(nameVal): print("姓名是:\(nameVal)"); // "姓名是:Tom James" case let .age(ageVal): print("年龄是:\(ageVal)"); }
写在后面
本来想着一周搞定的,结果中间有很多事耽误了,现在已经搞了两周还是没写完,那就后续再补一篇 :)。