//: Playground - noun: a place where people can play
import UIKit
var str = "類與結構體"
/*結構體
OC中結構體只可以定義屬性而不能定義方法。而在Swift中,結構體和類十分相似,其中既可以定義屬性也可以定義方法,但其不像類一樣具有繼承的特性。
使用struct來定義結構體,結構體中可以聲明變量或常量作爲結構體的屬性,也可以創建函數作爲結構體的方法,結構體使用點語法來調用其中的屬性和方法。
*/
//定義一個car
struct Car{
// 設置屬性-價格和品牌
var price:Int
var brand:String
var petrol:Int //耗油量
// 定義一個行路的方法
mutating func drave(){
if petrol>0 {
petrol -= 10
print("耗費了10升油")
}
}
// 定義一個加油的方法
mutating func addPetrol(){
petrol += 10
print("加了10升油")
}
}
var car = Car(price: 1000000, brand: "寶馬", petrol: 50)
print("這是一輛\(car.brand),汽車價格是\(car.price),油量\(car.petrol)")
car.drave()
print("剩餘\(car.petrol)升")
//注意,Swift語言中的數據類型分爲值類型和引用類型,結構體、枚舉等其他除類之外的所有數據類型都屬於值類型,只有類是引用類型的。值類型和引用類型的最大區別在於當進行數據傳遞時,值類型總是被複制,而引用類型不會被複制,引用類型是通過引用計數來管理其生命週期的。
/*
類
類是較結構體更加高級的一種數據類型。簡單的理解,類是編程世界中萬物的抽象,使用類可以模擬萬物的對象。Swift語言中使用class來聲明類。
*/
class CarClass{
var price:Int
var brand : String
var petrol: Int
//
func drave() {
if petrol>0 {
petrol -= 1
}
}
func addPetrol() {
petrol += 1
}
init(price:Int,brand:String,petrol:Int) {
self.price = price
self.brand = brand
self.petrol = petrol
}
}
//由此可以看出,類和結構體創建屬性和方法的代碼基本一樣。不同的是,結構體不需要提供構造方法,會自動根據屬性生成一個構造方法;類則要求提供構造方法,在init()工作方法中,完成對類中所有屬性的賦值操作
var car1 = CarClass(price: 1000000, brand: "奔馳", petrol: 100)
print(car1.price)
var car2 = car1//1000000
car2.price = 999999
print(car1.price)//999999
print(car2.price)//999999
//由上面的代碼可以看出如果將類的實例,傳遞給一個新的變量,那麼修改新的變量會影響原始變量。
/*
繼承
繼承是類獨有的特點,子類和父類通過繼承關係進行關聯,並且子類可以對父類進行擴展。Swift語言中,不繼承任何類的類稱爲基類,繼承而來的類稱爲子類。在編程中,子類會繼承父類的屬性和方法,子類也可以定義自己的屬性和方法。
*/
//創建一個交通的工具基類
class Transportation {
var petrol : Int
func drave() {
// 具體有子類實現
if petrol == 0 {
self.addPetrol()
}
print("父類drave方法")
}
func addPetrol() {
petrol += 10
}
init(petrol: Int) {
self.petrol = petrol
}
}
//創建一個船類,繼承Transportation
class Boat: Transportation{
//自己的屬性
var floor:Int
// 重寫父類方法
override func drave() {
super.drave()
print("海上航行了50km")
self.petrol -= 2
}
/*
init(floorCount :Int) {
floor = floorCount
}
會報錯
“Super.init isn't called on all paths before returning from initializer”
在子類的構造器中,父類的成員變量必須通過父類的designated initializer進行初始化。也就是說,我們必須調用super.init,而且在調用super.init之前不能使用和訪問任何父類的成員變量,否則“use of 'self' in property access 'name' before super.init initializes self”
*/
init(floor:Int,petrol:Int) {
self.floor = floor
super.init(petrol: petrol)
}
}
//創建一個飛機類
class Airplane:Transportation{
var height:Float
init(height:Float,petrol:Int) {
self.height = height
super.init(petrol: petrol)
}
override func drave() {
super.drave()
print("在天上飛行可1000km")
self.petrol -= 2
}
}
//創建船實例,飛機實例
var boat = Boat(floor: 5, petrol: 30)
var airplane = Airplane(height: 10000, petrol: 20)
//調用drave()方法
boat.drave()
airplane.drave()
//注意,Swift語言中還提供了一個final關鍵字,final關鍵字用於修飾某些終極的屬性、方法或者類。被final修的屬性和方法不能被子類繼承
/*類和結構體的作用十分相似,但是兩者有着本質的不同,他們在數據傳遞的機制不同,分別適用於不同的應用場景
下面的幾種情況下建議使用結構體:
a.要描述的數據類型其中只有少量的簡單數據類型的屬性
b.要描述的數據類型在數據傳遞時需要以複製的方式進行
c.要描述的數據類型中的所有屬性在進行傳遞時需要以複製的方式進行
d.不需要繼承另一個數據類型
關於值類型和引用類型,應該注意,如果對值類型進行比較操作,應使用等於運算符“==”;對引用類型進行比較,應使用等同運算符“===”
其實在Swift語言中,Array、String、Dictionary、Set這些數據都是採用結構體來實現的,因此在Swift語言中,Array、String、Dictionary、Set在數據傳遞時總是被複制。但是在蘋果的官方文檔有介紹:在開發者的代碼中,看似複製行爲總會發生。然而,Swift語言在幕後會控制只有絕對需要時纔會進行真正的複製操作,以確保性能最優,因此在實際開發中沒必要回避複製行爲來確保性能。
*/
//練習
//1、設計一個學生類,爲每個學生設計姓名、性別和年齡屬性,並提供一個學習的方法
enum Sex{
case 男
case 女
}
class Student{
let name: String
let sex: Sex
let age: Int
init(name:String,sex:Sex,age:Int) {
self.name = name
self.sex = sex
self.age = age
}
// 學習的方法
func study() {
print("\(self.name)在學習,性別:\(self.sex),年齡:\(self.age)")
}
}
//創建實例
var student = Student(name: "張三", sex: .男, age: 18)
student.study()
//2、結合上面的學生類,設計一個班級類,其中需要有班級名、學生人數和班長3個屬性,並設計轉入和轉出學生的方法。
class ClassStu{
var name: String
var numCount : Int//人數
var monitor :Student
init(name:String,numCount:Int,monitor:Student) {
self.name = name
self.numCount = numCount
self.monitor = monitor
}
func addStudent() {
numCount += 1
print("轉入了一個學生,現在一共\(self.numCount)名學生")
}
func deleStudent() {
numCount -= 1
print("轉出了一名學生,現在一共\(self.numCount)名學生")
}
// 描述方法
func description() {
print("\(self.name),共有\(self.numCount)名學生,班長是\(self.monitor.name)")
}
}
//創建一個班長
var monitor = Student(name: "莉莉", sex: .女, age: 19 )
//創建一個班級
var class1 = ClassStu(name: "二年級一班", numCount: 35, monitor: monitor)
class1.addStudent()
class1.description()