2024 Swift 最新面试题及答案
基础部分
Swift访问控制
访问级别 | 描述 | 同一模块内可见 | 不同模块内可见 | 示例 |
---|---|---|---|---|
open |
最高访问级别,允许实体被定义模块外的其他模块访问,也可以被继承和重写。 | ✅ | ✅ | 用于公共框架和库的公共接口,如一个开源框架的公共API。 |
public |
允许实体被定义模块外的其他模块访问,但不能被继承和重写。 | ✅ | ❌ | 用于公共接口的内部实现,如一个库的具体实现细节。 |
internal |
默认访问级别,允许实体在定义模块内部任何地方访问,但不能被定义模块外的其他模块访问。 | ✅ | ❌ | 用于应用程序或框架的内部实现,如应用程序的各个组件之间的交互。 |
fileprivate |
限制实体只能在其定义的文件内部访问。 | ✅ | ❌ | 用于实现细节和私有功能,如一个类的内部细节只对该类的其他成员可见。 |
private |
限制实体只能在其定义的作用域(类、结构体、枚举或扩展)内部访问。 | ✅ | ❌ | 用于实现细节和私有功能,如一个结构体内部的数据成员只能在该结构体的方法中使用。 |
示例:
// ModuleA.swift
open class MyOpenClass {
}
public class MyPublicClass {
}
internal class MyInternalClass {
}
fileprivate class MyFilePrivateClass {
}
private class MyPrivateClass {
}
// ModuleB.swift
import ModuleA
// 在 ModuleB.swift 中可以访问 MyOpenClass、MyPublicClass 和 MyInternalClass
// 但不能访问 MyFilePrivateClass 和 MyPrivateClass
Swift Any
、AnyObject
和Generics
区别
这里是关于 Any
、AnyObject
和泛型的一些区别:
Any
:Any
是Swift
中的⼀种类型擦除(type erasure)的概念,是⼀个协议(protocol)。- 使用
Any
声明的变量可以存储任何类型的值,包括值类型和引⽤类型。 Any
是Swift
中的一个特殊类型,用于表示任意类型的实例。- 使⽤
Any
时,Swift
编译器会放弃类型检查,因此需要⼩⼼使⽤,避免类型错误。 - 例如:
var anyValue: Any
anyValue = 42
print(anyValue) // 输出: 42
anyValue = "Hello, Swift"
print(anyValue) // 输出: Hello, Swift
anyValue = [1, 2, 3]
print(anyValue) // 输出: [1, 2, 3]
AnyObject
:AnyObject
是Swift
中的⼀个协议(protocol
),表示任何类(引⽤类型)类型的实例。- 使用
AnyObject
声明的变量可以存储任何类类型的实例,但不能存储结构体、枚举或其他类型的实例。 AnyObject
是一个协议类型,所有类都隐式地遵循了AnyObject
协议。- 例如:
var anyObjectValue: AnyObject
class MyClass {
}
anyObjectValue = MyClass()
print(anyObjectValue) // 输出: <MyClass>
class YourClass {
}
anyObjectValue = YourClass()
print(anyObjectValue) // 输出: <YourClass>
Generics
:- 泛型是
Swift
中的⼀种编程技术,⽤于编写可以处理任意类型的代码。 - 泛型允许在编译时编写灵活的代码,以便在使用时指定类型。
- 使用泛型可以编写更加灵活和可重用的代码,而不需要在编译时知道确切的类型。
- 泛型可以用于函数、方法、类、结构体和枚举等地方,使得这些实体可以与任意类型一起工作。
- 泛型代码在编译时会进⾏类型检查,避免了使⽤
Any
时的类型不确定性问题。 - 例如:
- 泛型是
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
let temp = a
a = b
b = temp
}
var intValue1 = 42
var intValue2 = 10
swapTwoValues(&intValue1, &intValue2)
print("intValue1: \(intValue1), intValue2: \(intValue2)") // 输出: intValue1: 10, intValue2: 42
var stringValue1 = "Hello"
var stringValue2 = "World"
swapTwoValues(&stringValue1, &stringValue2)
print("stringValue1: \(stringValue1), stringValue2: \(stringValue2)") // 输出: stringValue1: World, stringValue2: Hello
简而言之,Any
和 AnyObject
是用于处理不同类型的实例的机制,而泛型则是一种编写灵活、可重用代码的机制。Any
可以表示任何类型的实例,而 AnyObject
只能表示类类型的实例。Generics 允许在编译时编写灵活的代码,以处理不同类型的数据。
Swift final
关键字 ⽤过没 主要⽤来⼲嘛
final
关键字在 Swift 中用于限制类、属性和方法的继承和重写。具体来说,final
有以下用途:
-
限制类的继承:通过在类的定义前加上
final
关键字,可以防止其他类继承该类。这样做可以确保类的实现不会被修改或扩展,从而提高代码的安全性和稳定性。final class FinalClass { } // OtherClass: FinalClass // 编译错误,FinalClass 不能被继承
-
限制属性的重写:通过在属性的定义前加上
final
关键字,可以防止子类重写该属性。这样做可以确保父类的属性在子类中保持不变。class ParentClass { final var finalProperty: Int = 42 } class ChildClass: ParentClass { // override var finalProperty: Int // 编译错误,finalProperty 不能被重写 }
-
限制方法的重写:通过在方法的定义前加上
final
关键字,可以防止子类重写该方法。这样做可以确保父类的方法在子类中保持不变。class ParentClass { final func finalMethod() { print("ParentClass final method") } } class ChildClass: ParentClass { // override func finalMethod() { // 编译错误,finalMethod 不能被重写 // print("ChildClass override method") // } }
总之,final
关键字用于限制类、属性和方法的继承和重写,从而提高代码的安全性和稳定性。特别是在框架或库中希望确保类的⾏为不被修改时⾮常有⽤。
Swift 的 static
和class
区别
static
和class
关键字都可以用来声明类型级别的属性和方法
- 静态属性和方法的使用方式:
static
:可以用在类、结构体和枚举中,用来声明类型级别的属性和方法。在类中,static
修饰的属性和方法可以被子类继承和重写。class
:只能用在类中,用来声明类型级别的属性和方法。在类中,class
修饰的属性和方法可以被子类继承,但是只有类方法可以被子类重写。
- 重写:
static
:无法在子类中重写。class
:只能用于类方法,可以在子类中进行重写。
- 继承:
static
:可以被继承。class
:可以被继承
- 类成员引用:
static
:可以直接通过类型名称来访问,例如 ClassName.staticMember。class
:只能通过实例或子类来访问,例如 instanceOfClassOrSubclass.classMember。
- 示例