MST

星途 面试题库

面试题:Swift 中结构体和类在数据类型使用上的区别

请详细阐述在 Swift 中结构体和类在数据类型方面的不同点,包括存储属性、引用方式、初始化过程等方面,并举例说明。
14.6万 热度难度
编程语言Swift

知识考点

AI 面试

面试题答案

一键面试

存储属性

  • 结构体:结构体是值类型,它的实例在被传递或赋值时,会进行值拷贝。每个实例都有自己独立的存储属性副本。例如:
struct Point {
    var x: Int
    var y: Int
}

var point1 = Point(x: 10, y: 20)
var point2 = point1
point2.x = 30
print(point1.x) // 输出 10,说明 point1 和 point2 是不同的副本
  • :类是引用类型,类的实例在被传递或赋值时,传递的是引用(内存地址),多个变量可以引用同一个实例,共享存储属性。例如:
class Rectangle {
    var width: Int
    var height: Int
    init(width: Int, height: Int) {
        self.width = width
        self.height = height
    }
}

var rect1 = Rectangle(width: 100, height: 200)
var rect2 = rect1
rect2.width = 150
print(rect1.width) // 输出 150,说明 rect1 和 rect2 引用同一个实例

引用方式

  • 结构体:结构体的值拷贝特性使得它在函数参数传递、赋值等操作时,都是传递完整的值,适用于数据量较小、希望数据独立的场景。例如,函数接收一个结构体参数时,函数内部对参数的修改不会影响外部的原始实例。
struct Size {
    var width: Double
    var height: Double
}

func modifySize(_ size: Size) {
    var localSize = size
    localSize.width = 50.0
    localSize.height = 50.0
}

var mySize = Size(width: 100.0, height: 100.0)
modifySize(mySize)
print(mySize.width) // 输出 100.0,mySize 未被修改
  • :类的引用特性使得在函数参数传递、赋值等操作时,传递的是引用,适用于数据量较大、希望共享数据的场景。例如,函数接收一个类的实例作为参数时,函数内部对实例属性的修改会影响外部的原始实例。
class Circle {
    var radius: Double
    init(radius: Double) {
        self.radius = radius
    }
}

func modifyCircle(_ circle: Circle) {
    circle.radius = 10.0
}

var myCircle = Circle(radius: 5.0)
modifyCircle(myCircle)
print(myCircle.radius) // 输出 10.0,myCircle 被修改

初始化过程

  • 结构体:结构体有默认的成员逐一初始化器,即使没有显式定义初始化器,也可以通过成员逐一初始化器来初始化实例。例如:
struct Color {
    var red: Int
    var green: Int
    var blue: Int
}

let myColor = Color(red: 255, green: 0, blue: 0) // 使用默认的成员逐一初始化器

结构体也可以自定义初始化器,并且在自定义初始化器中,必须确保所有存储属性都被初始化。

struct Rectangle {
    var width: Int
    var height: Int
    init(sideLength: Int) {
        width = sideLength
        height = sideLength
    }
}

let square = Rectangle(sideLength: 5)
  • :类必须为所有存储属性提供初始值,可以在属性声明处提供默认值,也可以在初始化器中进行初始化。类有指定初始化器和便利初始化器,指定初始化器必须调用其直接父类的指定初始化器,以确保父类的所有属性也被正确初始化。例如:
class Animal {
    var name: String
    init(name: String) {
        self.name = name
    }
}

class Dog: Animal {
    var breed: String
    init(name: String, breed: String) {
        self.breed = breed
        super.init(name: name)
    }
}

let myDog = Dog(name: "Buddy", breed: "Labrador")

便利初始化器必须调用同一个类的另一个初始化器,最终也会调用到指定初始化器。例如:

class Dog {
    var name: String
    var breed: String
    init(name: String, breed: String) {
        self.name = name
        self.breed = breed
    }
    convenience init() {
        self.init(name: "Unknown", breed: "Unknown")
    }
}

let defaultDog = Dog()