枚举
csharp
enum Sex {
case woman
case man
}
var a = Sex.woman
// 当a的类型确定好之后,可以采用简写
a = .man
枚举的递归,枚举的默认值等用的很少。
结构体和类
结构体可以不给默认值,类如果没有默认值,必须添加初始化方法
ini
class Student{
var name:String = ""
var age:Int = 0
}
class Student1{
var name:String = ""
var age:Int
init(){
// 只要有变量没有默认值,就必须提供初始化方法
age = 20
}
}
var s = Student()
var s1 = Student1()
// 结构体是值类型,类是引用类型
// 值类型的优点是速度快,分配在栈空间
var pp = Person()
pp.age = 20
var pp1 = pp
pp.age = 200
print(pp1.age) //还是默认值20
var ss = Student()
ss.age = 20
var ss1 = ss
ss.age = 200
print(ss1.age) // 200,已经被修改了
// 恒等运算符 === !==
// 只有2个变量或者常量指向同一个内存空间才算
if ss === ss1 {
print("===")
}
存储属性
ini
// 存储属性
struct Student{
var name:String
var age:Int
}
class Student1{
var name:String = ""
var age:Int = 0
}
let s = Student(name: "", age: 20)
//s.age = 100 语法错误
// 类可以被修改
let s1 = Student1()
s1.age = 200
延迟存储属性
swift
struct Person{
lazy var name:String = {
print("person name 初始化")
return "杜甫"
}()
var age:Int
}
class Person1 {
lazy var name:String = {
print("person1 name 初始化")
return "杜甫"
}()
var age:Int
init(){
age = 10
}
}
var p = Person(age: 20)
print(p.age)
print(p.name) // 使用的时候才初始化
var p1 = Person1()
print(p1.age)
print(p1.name) // 使用的时候才初始化
计算属性
scss
// 计算属性
struct Squre{
var width:Double = 0
var area:Double {
get{
return width * width
}
set(v){
width = sqrt(v)
}
}
}
class Squre1{
var width:Double = 0
var area:Double {
get{
// 也可以直接省略return
return width * width
}
// set(v){
// width = sqrt(v)
// }
set{
// 也可以用newValue
width = sqrt(newValue)
}
}
// 只读属性
var perimeter:Double{
width * 4
}
}
var s = Squre()
s.area = 100
print(s.width)
s.width = 200
print(s.area)
var s1 = Squre1()
s1.area = 100
print(s1.width)
s1.width = 200
print(s1.area)
print(s1.perimeter)
属性观察器
作用域
- 自定义的存储属性
- 继承的存储属性和计算属性
swift
class Student{
var age:Int = 0 {
willSet{
print("will set ", newValue)
}
didSet{
print("did set ", oldValue)
}
}
}
var s = Student()
s.age = 1000
方法
swift
// 方法
struct Student{
var name:String = ""
var age:Int = 0
//因为结构体是值类型, 默认是let不能修改self.因此必须使用mutaing声明
mutating func changeAge(by age:Int){
// 属性和形参同名称,需要用self区分
self.age = age
}
}
class Student1{
var name:String = ""
var age:Int = 0
func changeAge(by age:Int){
self.age = age
}
}
var s = Student()
s.changeAge(by: 20)
print(s.age)
var s1 = Student1()
s1.changeAge(by: 20)
print(s1.age)
类方法
scss
// 结构体方法和类方法
@MainActor
struct Student {
static var count: Int = 1
static func add() {
count += 1
}
static func dec() {
count -= 1
}
static func getTotal() -> Int {
return count
}
}
// static和class都是属于类方法
// static不能被子类重写
// class可以被子类重写
@MainActor
class Student1 {
static var count: Int = 1
static func add() {
count += 1
}
class func dec() {
count -= 1
}
class func getTotal() -> Int {
return count
}
}
Student.add()
print(Student.getTotal())
Student.add()
Student.add()
print(Student.getTotal())
Student.dec()
print(Student.getTotal())
Student1.add()
print(Student1.getTotal())
Student1.add()
Student1.add()
print(Student1.getTotal())
subscript 下标语法
final修饰的成员变量,方法,类方法都不能重写
swift
struct Student {
var age: Int = 0
subscript(index: Int) -> Int {
get {
return age
}
set {
age = newValue
}
}
}
class Student1 {
var age: Int = 0
subscript(index: Int) -> Int {
get {
return age
}
set {
age = newValue
}
}
}
var s = Student()
s[0] = 100
print(s[2])
var s1 = Student1()
s1[100] = 20
print(s1[20])
// 这里只能通过下标获取数据,不能写入数据
struct Student2 {
var age: Int = 0
subscript(index: Int) -> Int {
return age * index
}
}
var s2 = Student2()
//s2[10] = 100 语法错误
print(s2[2000])
继承
swift
class Animal{
var age:Int = 0
func eat(){
print("animal eat")
}
func drink(){
print("animal drink")
}
final func sleep(){
print("animal sleep")
}
}
class Person :Animal {
var name:String = ""
// 覆盖父类的方法需要写override
override
func drink() {
// 也可以在子类通过super调用父类的方法
super.drink()
print("people drink water")
super.sleep()
}
}
var p = Person()
p.eat()
p.drink()
构造函数
- init函数必须先调用父类的init函数
required init定义的函数,子类必须重写
swift
// 构造函数
// 没有默认值,必须手动写一个init函数
struct Student{
var name:String
var age:Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
// Student1会自动生成一个init函数
struct Student1{
var name:String = ""
var age:Int = 0
}
var s = Student(name: "李白", age: 20)
var s1 = Student1()
// 因为有默认值,所以可以只给其中的部分属性赋值
var s2 = Student1(name:"hello")
print(s2.age)
便利构造器
- 只能作用于class,不能作用在struct,enum
- 必须调用其它init函数先进行初始化
- 便利构造器只能调用当前类的构造函数和便利构造器,不能调用父类的便利构造器
- 子类不能调用父类的便利构造器
swift
class Person {
var name: String
var age: Int
// 1. 指定构造器(主入口,初始化所有属性)
init(name: String, age: Int) {
self.name = name
self.age = age
}
// 2. 便利构造器:只传名字,年龄默认 0
convenience init(name: String) {
// 必须先调用本类指定构造器
self.init(name: name, age: 0)
}
// 3. 便利构造器:无参,全部默认
convenience init() {
self.init(name: "未知")
}
}
// 三种创建方式,全部合法
let p1 = Person(name: "小明", age: 20)
let p2 = Person(name: "小红")
let p3 = Person()
deinit
kotlin
class Student{
deinit{
//1.用来释放资源
//2. 验证Sdudent对象确实被释放了
}
}
循环引用
swift
// 这里就不会释放内存
class Student {
var p: Person?
deinit {
print("sudent 释放了")
}
}
class Person {
var s: Student?
deinit {
print("person 释放了")
}
}
var s: Student? = Student()
var p: Person? = Person()
s?.p = p
p?.s = s
s = nil
p = nil
// 改成weak
// 改成unowned但是不能访问,如果访问的时候空会报错
class Student {
weak var p: Person?
deinit {
print("sudent 释放了")
}
}
class Person {
unowned var s: Student?
deinit {
print("person 释放了")
}
}
var s: Student? = Student()
var p: Person? = Person()
s?.p = p
p?.s = s
s = nil
p = nil
swift
// 闭包导致的循环引用
class Test {
var closure: (() -> Void)?
deinit {
print("Test 销毁")
}
init() {
// 闭包强捕获 self → 自循环引用
closure = {
print(self)
}
}
}
var t: Test? = Test()
t = nil
// deinit 不执行
// 闭包必须使用weak
class Test {
var closure: (() -> Void)?
deinit {
print("Test 销毁")
}
init() {
// 弱捕获 self
closure = { [weak self] in
guard let self = self else { return }
print(self)
}
}
}
var t: Test? = Test()
t = nil
// 正常打印销毁