//: 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()