学习swift有一段时间了,有很多关键字例如var let func class 等等很多非常常用的,在这里就不做说明了,这篇文章选取了一些区别于OC 的关键词来说一说 。
- lazy :懒加载。swift 中我们在使用 lazy 修饰属性时,必须声明属性是变量。而且我们需要显示的指定属性的类型。对该属性进行一个赋值语句用来首次访问时使用。与OC 不同的是可以不需要判断里面是否为空,Swift懒加载的执行顺序是如果这个变量没有值,才会执行闭包。
注意的是需要用var来修饰,因为常量必须在实例构建时赋值
lazy var name: String = "Hello"
lazy var nameLabel: UILabel = {
let label = UILabel()
label.text = "hello,swift"
return label
}()
- struct:使用struct关键字去声明结构体,Swift中的结构体并不复杂,与C语言的结构体相比,除了成员变量,还多了成员方法。使得它更加接近于一个类。个人认为可以理解为是类的一个轻量化实现。比如:
struct Person {
var name:String
var age:Int
func introduce(){
print("我叫:\(name),今年\(age)岁")
}
}
var person = Person(name: "gp",age: 18)
person.name = "gp"
print("person.name = \(person.name)")
person.introduce()
/**
输出结果为:
person.name =gp
"我叫:gp,今年18岁"
*/
语法与C语言或者OC类似,Swift中的结构体,在定义成员变量时一定要注明类型。另外要注意一下的是,结构体属于值类型,而Swift中的类属于引用类型。
下面扩展一下什么叫做值类型,什么是引用类型。
值类型和引用类型实际上就是指对象的传递方式分别是 按值传递 和 按地址传递。
值类型的赋值为深拷贝(Deep Copy),值语义(Value Semantics)即新对象和源对象是独立的,当改变新对象的属性,源对象不会受到影响,反之同理。
除了 Int类型,诸如:CGFloat,Bool,Character,Array,struct等,这些值类型的对象都可以使用inout修饰,达到使用引用的方式传递的目的。
引用类型的赋值是浅拷贝(Shallow Copy),引用语义(Reference Semantics)即新对象和源对象的变量名不同,但其引用(指向的内存空间)是一样的,因此当使用新对象操作其内部数据时,源对象的内部数据也会受到影响。
举个🌰
struct SomeStruct {
var data: Int = -1
}
class SomeClass {
var today = "Monday"
}
**值类型 按值传递:**
var a = SomeStruct()
var b = a // a复制一份,并将副本赋值给了b
a.data = 42 // a的数据改变了,但是b的并没有改变
print("\(a.data), \(b.data)")//42,-1
**引用类型 按址传递:**
//引用类型的赋值行为其实是隐式的创建了一个共享的实例,作为原始类型的引用。
//下面的例子中,两个变量都会引用唯一的那个共享实例的数据,所当改变这两个变量中任何一个的数据,都会同样作用于原始类型的数据:
var week = SomeClass()
var week2 = week
week2.today = "Tues."
print("\(week.today),\(week2.today)")//"Tues.,Tues."
- inout:将值类型的对象用引用的方式传递。
inout关键字,可以使得值类型的对象和引用类型的对象一样,以按址传递的方式进行操作,这里的操作不仅包含上述例子中的赋值操作,也包含了函数的参数传递行为。
通俗的举个例子:我们在使用函数传递一个Int类型对象的时候,通常会将这个对象的值传递进去了。但是如果使用inout修饰对象的类型,则可以将变量的地址传入函数。就像下面这个handle函数一样。
func test(){
var a:Int = 5
handle(a:&a) // 注意这里使用了取址操作
print(a) // 6
}
func handle(a: inout Int){
print(a) //5
a = a + 1 //如果没有inout修饰的话,这句代码将会报错,主要意思是不能改变一个let修饰的常量。
}
最终,我们在test 函数中打印的变量a的值被改变了。
- override:重写。如果我们要重写某个方法, 或者某个属性的话, 我们需要在重写的变量前增加一个override关键字。
- final: 防止重写,
- final不能修饰结构体和枚举
- final修饰符只能修饰类,表明该类不能被其他类继承,也就是它没资格当父类。
- final修饰符也可以修饰类中的属性、方法,但前提是该类并没有被final修饰过。
可以将类或者类中的部分实现保护起来,从而避免子类破坏
import UIKit
class MondayClass: NSObject {
final var today = "1"
final func whatTheDay() {
}
}
//如果放在class前面修饰的话 那么这个类将不能被继承
class TestMonday: MondayClass {
override func whatTheDay() {//Instance method overrides a 'final' instance method
}
}
- typealias:
在Swift中,使用关键字typealias定义类型别名(typealias就相当于objective-c中的typedef),就是将类型重命名,看起来更加语义化。比如:
typealias Success = (_ result: String) -> Void
typealias Failure = (_ error: String) -> Void
func excuteNetworking(_ successBlock: Success, failBlock: Failure) {
}
- deinit :属于析构函数,析构函数(destructor) 与构造函数相反。当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。
与OC 中的dealloc一个意思
写法:
deinit{
self.removeObserver(self, forKeyPath: "bounds")
NSNotificationCenter.defaultCenter().removeObserver(self)
}
一般可以用来:
销毁对象、
KVO移除、
移除通知、
NSTimer销毁等。
- static:
static 可以修饰存储属性,static 修饰的存储属性称为静态变量(常量)。
static 修饰的静态方法不能被重写,class 修饰的类方法可以被重写。
首先先来了解两个概念
- 存储属性:就是存储在特定类或结构体的实例中的常量或变量。例如最简单的:
class Man {
//可变存储属性
var walk: Int = 20
//不能变存储属性
let run:Int = 100
}
- 计算属性:不直接存储值,而是提供一个“getter”来获取值和一个可选的“setter”来设置值,例如:
//计算属性 只有getter方法 表示只读
var walker :Int {
return 1
}
//等价于
var walker:Int{
get{
return 1
}
}
再来看一个可读可写的计算属性:
struct Point {
var x = 0.0, y = 0.0
}
struct Size {
var width = 0.0, height = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
var center: Point {
get {
let centerX = origin.x + (size.width / 2)
let centerY = origin.y + (size.height / 2)
return Point(x: centerX, y: centerY)
}
set(newCenter) {
origin.x = newCenter.x - (size.width / 2)
origin.y = newCenter.y - (size.height / 2)
}
}
}
//赋值调用
var square = Rect(origin: Point(x: 0.0, y: 0.0),size: Size(width: 10.0, height: 10.0))
print("square.origin was at (\(square.center))")//5,5
square.center = Point(x: 15.0, y: 15.0)
print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
// 输出 "square.origin is now at (10.0, 10.0)”
好了,可以继续static
class Man {
//存储属性
static var walk: Int = 20
//计算属性
static var run: Int{
return 10
}
//类方法
static func walkRace() -> Int {
return Man.walk
}
}
class SuperMan: Man {
// Cannot override static method
override static func walkRace() -> Int {//报错
return 100
}
//Cannot override with a stored property 'walk'
override static var walk: Int = 30//报错
}
但是如果是class修饰的方法和属性是可以重写的,如下:
class Man {
//存储属性
static var walk: Int = 20//注意: 这样的存储类型是不能倍class修饰的
//计算属性
class var run: Int{
return 10
}
//类方法
class func walkRace() -> Int {
return Man.walk
}
}
class SuperMan: Man {
override class func walkRace() -> Int {
return 20
}
未完待续。。。>_<
网友评论