Swift -- 7.3 类和结构体
swift的类和结构体高度相似,无论是定义语法还是用法上,swift的类和结构体都具有高度的相似性
区别是:结构体不支持继承(自然也不支持类型转换了。。。。。这个,还不太理解)
结构体不支持定义析构器
结构体是值类型,而类是引用类型
苹果的官方文档中说结构体的使用场景不多,主要还是应该使用类
那么哪些场景需要用到结构体呢:
苹果的官方文档表示,当满足以下一个或多个条件时,应该使用结构体
*结构体的主要目的是用于封装少量相关的简单数据值
如果程序需要让该实例在赋值或参数传递时会自动复制副本,则应该使用结构体
如果程序明确该类型无须继承另一个已有的的类或被其他类继承,则可以考虑使用结构体
一个类中包含三种成员:构造器,属性,方法
swift语言通过类名后添加圆括号来表示调用构造器,从而返回该类的实例
如果程序员自己没有写构造器,系统会提供一个默认的无参的构造器,如果自己写了,系统就不提供默认的构造器
class修饰的成员(类成员)不能访问没有class修饰的成员(实例成员)
定义结构体和定义类的主要区别是:结构体不支持继承,因此结构体不能使用final修饰
如果程序员没有为结构体提供构造器,系统则会为该结构体提供两个构造器:一个无参的构造器,一个初始化所有存储属性的构造器
class,static两个修饰符的作用几乎完全相同,只是使用场景不同。定义类时,使用class修饰类中成员,将遮羞成员转成类型相关的成员,没有该修饰符的是实例成员;定义结构体或枚举时,使用static修饰枚举或结构体的成员,将这些成员转成类型相关的成员,没有该修饰符修饰的是实例成员,所以static和class两个修饰符不会同时出现
swift语言要求类中定义的存储属性必须指定初始值,要么在定义时指定初始值,要么在构造器中指定初始值
swift的构造器隐式的将self作为返回值
定义和创建实例
//定义一个person类
class Person
{
var name : String = ""
var age : Int = 0
func say(content:String)
{
print(content)
}
}
//定义一个dog结构体
struct Dog
{
var name : String
var age : Int
func run()
{
print("\(name) is running")
}
}
//创建实例
var p6:Person
p6 = Person()
var p5 = Person()
var p7 = p6
p6.name = "sun"
p6.say("swift is so easy")
print(p6.name)
print(p5.name)
p6.name = "zhu"
print(p7.name)
var dogfff = Dog(name: "doggy", age: 4)
print(dogfff.age)
dogfff.run()
var dogggg = dogfff
dogggg.name = "happy"
print(dogfff.name)
使用===和!==来判断引用类型是否指向同一个实例
class User
{
var name:String
var age:Int
init(name:String , age:Int)
{
self.name = name
self.age = age
}
}
var u1 = User(name: "abe", age: 12)
var u2 = User(name: "abe", age: 12)
print(u1 === u2)
var u3 = u1
print(u3 === u1)
struct Level {
var grade:Int
}
var v1 = Level(grade: 1)
var v2 = Level(grade: 2)
//print(v1 === v2) 这里不能这样写,因为只有引用类型能这样比较
运算符重载
func == (left:User, right:User) -> Bool
{
return left.name == right.name && left.age == right.age
}
func != (left:User, right:User) -> Bool
{
return !(left == right)
}
var resultttt = u1==u2
print(resultttt)
存储属性
枚举不能定义实例存储属性,只有类和结构体才能定义实例存储属性;枚举,类,结构体都可以定义类型存储属性
在结构体中,声明的存储属性可以不赋予初始值,因为系统会自动生成一个构造器,用来赋予初始值
struct FixedLengthRange {
var start: Int
let length: Int
}
var rg = FixedLengthRange(start: 2, length: 10)
rg.start = 5
延迟存储属性
在第一次被调用时才会被计算初始值的属性,声明延迟存储属性需要使用lazy修饰符
延迟存储是一种延迟加载(lazy load)机制,当某个实例持有另一个创建成本较大的实例的引用时,使用延迟存储可以降低内存开销,从而提升程序性能
class Dept
{
var id : Int
var info : String
init(id : Int)
{
self.id = id
NSThread.sleepForTimeInterval(2)
self.info = "2 second late"
}
}
class User4 {
var id:Int = 0
lazy var dept = Dept(id: 20)//dept 属性会在被调用的时候才被初始化,提升了程序的性能
var nicks = [String]()
}
var usersss = User4()
usersss.nicks.append("sun")
usersss.nicks.append("qiqiqi")
print(usersss.nicks)
计算属性
枚举,结构体,类都可以定义计算属性
enum Seasonnn
{
case Spring, Summer, Fall, Winter
var info:String{
get{
print("the get method is running")
switch(self)
{
case .Spring:
return "flower"
default:
return "no"
}
}
set (newValue){
print("the set method is running and the pragmatic is \(newValue)")
}
}
}
var s = Seasonnn.Spring
print(s.info)
s.info = "baby"
//简化的set方法
enum Seasonnn2
{
case Spring, Summer, Fall, Winter
var info:String{
get{
print("the get method is running")
switch(self)
{
case .Spring:
return "flower"
default:
return "no"
}
}
set{
print("the set method is running and the pragmatic is \(newValue)")
}
}
}
/*
声明只读的计算属性
没有set方法,只有get方法
这里可以省略get这个关键字和花括号
*/
enum Seasonnn3
{
case Spring, Summer, Fall, Winter
var info:String{
get{
print("the get method is running")
switch(self)
{
case .Spring:
return "flower"
default:
return "no"
}
}
}
}
var ss = Seasonnn3.Spring
属性观察者机制
为了让程序能在属性被赋值时获得执行代码的机会,swift提供了属性观察者机制,属性观察者其实就是两个特殊的回调方法
willSet(newValue) 被观察的属性即将被赋值之前自动调用该方法
didSet(oldValue) 被观察的属性被赋值完成之后自动调用该方法
willSet部分可以显式指定
class People {
var name:String = "" {
willSet{
if(newValue.characters.count > 6) || (newValue.characters.count < 2){
print("the name you input is iligo")
}
else
{
print("set name success")
}
}
didSet{
print("set name over")
}
}
}
var jane = People()
jane.name = "d"
print(jane.name)//虽然这两个方法有监察作用,但是并不能阻止赋值的执行

浙公网安备 33010602011771号