-
類和結構體的共同點
a.定義存儲屬性
b.定義函數(shù)
c.定義下標,使用下表訪問自己的值
d.定義初始化設置自己的初始化狀態(tài)
e.擴展自己的功能
f.實現(xiàn)協(xié)議提供某種特定的標準功能 -
類和結構體的區(qū)別
a.類可以繼承,結構體不能繼承
b.類能夠在運行時檢查和解釋類實例的類型
c.Deinitializers使一個類的實例來釋放任何資源分配
d.類有引用計數(shù),允許對象被多次引用
// 定義類
class StudentC{
var name:String!
}
// 定義結構體
struct StudentS{
var name:String
}
在類中定義屬性必須要注意,如果你定義的存儲屬性不是可選值類型,必須進行初始化,不然編譯會報錯,但是結構體不會報錯,因為系統(tǒng)默認會給結構體創(chuàng)建初始化方法
// 定義類
class StudentC{
static var des:String = "學生的類"
var name:String!
func getName()->String{
return name
}
class func describe()->String{
return des
}
static func getClassDescribe()->String{
return des
}
}
// 定義結構體
struct StudentS{
static var des:String = "學生的結構體"
var name:String
static func describe()->String{
return "這是一個定義學生的類"
}
}
類可以使用關鍵字static class 修飾方法,但是結構體只能使用關鍵字static修飾
- 擴展下標
class StudentC{
var names:[String] = ["1","2","3","4","5"]
subscript (index:Int)->String?{
get{
if names.count <= index{
return nil
}
return names[index]
}
}
}
// 定義結構體
struct StudentS{
var names:[String] = ["1","2","3","4","5"]
subscript (index:Int)->String?{
get{
if names.count <= index{
return nil
}
return names[index]
}
}
}
// 執(zhí)行
let student1 = StudentC()
print(student1[8])
- 初始化
// 定義類
class StudentC{
var name:String
init( name:String) {
self.name = name
}
}
// 定義結構體
struct StudentS{
var name:String
init(name:String) {
self.name = name
}
}
let student1 = StudentC(name: "酷走天涯")
let student2 = StudentS(name: "XUJIE")
提示:
結構體默認會有初始化方法
struct StudentS{
var name:String
}
let student2 = StudentS(name: "xujie")
- 擴展功能
extension StudentC{
func describe()->String{
return "學生" + self.name
}
}
extension StudentS{
func describe()->String{
return "學生" + self.name
}
}
- 實現(xiàn)協(xié)議
// 定義一個協(xié)議
protocol Capacity{
func draw() // 協(xié)議方法
}
// 定義類
class StudentC:Capacity{
// 實現(xiàn)協(xié)議方法
internal func draw() {
}
var name:String
init( name:String) {
self.name = name
}
}
// 定義結構體
struct StudentS:Capacity{
// 實現(xiàn)協(xié)議方法
internal func draw() {
}
var name:String
}
- 繼承
// 定義基類
class Person{
var name:String
init( name:String) {
self.name = name
}
}
// 定義類
class StudentC:Person{
var score:Float
init( name:String,score:Float) {
self.score = score
super.init(name: name)
self.name = name
}
}
提示:
結構體不能繼承結構體
- mutating 關鍵字的作用
結構體和枚舉都是值類型,但是默認值類型的對象方法不能修改屬性值,但是要修改怎么辦呢?就必須在函數(shù)前面加mutating
//例子1
protocol Action{
var myY:Int{ mutating get}
}
struct Point{
var x:Int
var y:Int
// 結構體或者枚舉修改值必須在函數(shù)前面加mutating
mutating func modifyX(x:Int){
self.x = x
}
// 注意計算屬性,mutating 要加載getter方法前面
var myY:Int{
mutating get {
self.y = self.y*2
return y
}
}
}
// 例子2
struct Point {
var x = 0.0, y = 0.0
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
self = Point(x: x + deltaX, y: y + deltaY)
}
}
// 例子3
enum TriStateSwitch {
case off, low, high
mutating func next() {
switch self {
case .off:
self = .low
case .low:
self = .high
case .high:
self = .off
}
}
}
提示:
1.計算屬性setter方法不用修改屬性值不用添加mutating
2.計算屬性setter方法中修改屬性值的時候,一定要加mutating
- 檢測兩個對象地址是不是相同
class StudentC{
var name:String
init( name:String) {
self.name = name
}
}
let student1 = StudentC(name: "xujie")
let student2 = student1
if student1 === student2{
print("地址相同")
}
運行結果:
地址相同
結論:
類是引用類型,結構體是值類型,不能使用===/!== 判斷地址
- Deinitializers使一個類的實例來釋放任何資源分配
// 定義類
class StudentC{
var name:String
init( name:String) {
self.name = name
}
deinit {
// 釋放資源
}
}
提示:
結構體沒有deinit 方法
a. 什么時候用結構體
1.該結構的主要目的是封裝幾個相對簡單的數(shù)據(jù)值
2.如果你希望你的結構在傳遞的時候被賦值而不是引用
3.希望結構在傳遞的時候,內(nèi)部的屬性也被復制而不是引用
4.不需要繼承屬性或者方法
綜合建議:
結構體創(chuàng)建速度更快,內(nèi)存占用更小,如果需要使用復雜的運算,這個時候,就需要綜合考慮兩者的有缺點了。