sum 的完整 Swift 代码。
一、"既然能识别冒号,顺便识别类型很难吗?"
不难,一点都不难。 你说得对:语法分析 / 编译器做 "参数类型区分" 是常规操作,高中生写个简单递归下降解析器都能搞定。
Objective-C 不做,不是技术难,是历史设计 + 运行时模型限制:
- OC 的方法签名在 runtime 里只看名字 + 冒号个数,不看类型;
- 所有参数都被擦成
id,动态派发时靠名字找方法,不按类型分派; - 当年设计时就没打算支持 "同名字不同类型" 的重载,宁可强制改名。
一句话:不是做不到,是苹果当年不想做,后来为了兼容不敢改。
二、iOS 为什么还允许 Objective-C?不是全 Swift 了吗?
现实是:iOS 系统底层和大量框架依然是 Objective-C 写的 (UIKit、Foundation 等)。 Swift 是后来出的,为了兼容旧代码、旧框架、旧项目,必须保留 OC。
现状:
- 新项目推荐 Swift;
- 老项目、复杂项目、底层库、混编项目,大量 OC;
- 苹果没说 "废掉 OC",只是主推 Swift。
三、Swift 是 "基于 Objective-C 封装的高级版" 吗?
不完全是,这么说有点误导。
准确讲:
- Swift 是独立新语言,语法、类型系统、编译器都是新写的;
- 但为了能在苹果平台跑、能调用老框架,Swift 重度依赖 OC Runtime,并和 OC 双向兼容;
- 底层:Swift 会生成能被 OC Runtime 识别的类 / 方法,不是 "OC 语法糖",是能互操作的新语言。
类比:
- OC:老房子,结构旧,但很结实,家具(框架)全在里面;
- Swift:新房子,设计现代、安全、舒服,但门口装了通道,能直接走进老房子用老家具。
四、Swift 支持重载吗?
支持!完全支持!而且就是你想要的那种:
同名函数,参数个数不同 / 参数类型不同,都能共存,编译器自动选。
这就是你想要的:
swift
// 两个 Int
func sum(_ a: Int, _ b: Int) -> Int { a + b }
// 三个 Int
func sum(_ a: Int, _ b: Int, _ c: Int) -> Int { a + b + c }
// 两个 String(拼接)
func sum(_ a: String, _ b: String) -> String { a + b }
全部同名 sum,不冲突,正常编译,正常调用。
五、你那 3 个函数,完整 Swift 代码(可直接跑)
1. 全局函数版(最简单)
swift
// 1. 两个 Int 相加
func sum(_ a: Int, _ b: Int) -> Int {
return a + b
}
// 2. 三个 Int 相加
func sum(_ a: Int, _ b: Int, _ c: Int) -> Int {
return a + b + c
}
// 3. 两个 String 拼接
func sum(_ a: String, _ b: String) -> String {
return a + b
}
// 调用
let s1 = sum(10, 20) // 30
let s2 = sum(10, 20, 30) // 60
let s3 = sum("Hello", "World") // "HelloWorld"
print(s1, s2, s3)
2. 写成类方法(对应 OC 的 -[sum::])
swift
class MyMath {
// 两个 Int
func sum(_ a: Int, _ b: Int) -> Int {
a + b
}
// 三个 Int
func sum(_ a: Int, _ b: Int, _ c: Int) -> Int {
a + b + c
}
// 两个 String
func sum(_ a: String, _ b: String) -> String {
a + b
}
}
let m = MyMath()
let x1 = m.sum(1, 2)
let x2 = m.sum(1, 2, 3)
let x3 = m.sum("A", "B")
六、一句话总结你的核心不爽
- Objective-C:只认名字 + 冒号,不认类型 → 不支持重载 → 你得改名(sumInt2 /sumStr)
- Swift:名字 + 个数 + 类型都认 → 完美支持重载 → 三个 sum 直接写,干净!
要不要我把这三个 Swift 函数再给你转成对应的 OC 写法,并标注为什么 OC 必须改名?
Swift和object-c是不是完全不同的编绎器,理论上可以说完全是2个东西?只是SWIFT有些语法兼容OBJECT-C,让新老程序员可以共用部分代码?
搜索 3 个关键词,参考 18 篇资料
结论先说:编译器前端是两套、后端共用一套;语言设计是两套、运行时部分共享。可以说 "两个东西",但不是完全割裂,是 "同基座、不同上层"。
下面拆开讲清楚(尽量人话):
一、编译器:前端完全不同,后端共用 LLVM
1)Objective‑C
- 编译器前端:Clang(LLVM 子项目)
- 负责:OC 语法解析、生成 AST、类型检查,输出 LLVM IR
2)Swift
- 编译器前端:Swift Compiler(自己独立写的)
- 负责:Swift 语法解析、类型推断、泛型处理、生成 AST,也输出 LLVM IR
3)共同点
- 两者都把自己的语法翻译成 同一种中间代码 LLVM IR
- 然后交给 同一个 LLVM 后端做优化、生成机器码(arm64/x86_64)
所以:
- 前端:两个完全不同的编译器(语法规则、类型系统、解析逻辑都不一样)
- 后端:共用同一个 LLVM
打比方:
- OC 是 "中文 → 翻译器 A → 英语(LLVM IR)→ 同一个机器"
- Swift 是 "日文 → 翻译器 B → 英语(LLVM IR)→ 同一个机器"
二、语言本身:完全独立设计,不是 "OC 语法糖"
你说的很接近:
"只是 Swift 有些语法兼容 OC,让新老程序员可以共用部分代码"
更准确是:
- Swift 不是基于 OC 改的,是苹果 2014 年从零设计的新语言
- 设计目标:干掉 OC 的痛点(动态、不安全、语法丑、不支持重载)
- 同时:强制兼容 OC 生态(因为 UIKit、Foundation 全是 OC 写的,不能重来)
核心差异(一眼看懂)
- Objective‑C :动态语言 ,消息派发(
objc_msgSend),运行时才找方法,不支持重载 - Swift :静态强类型语言 ,编译期确定类型 / 方法,原生支持重载、泛型、可选值
所以:
- 语法、类型系统、内存模型、派发机制,全是两套
- 不是 "OC 高级版",是全新语言 + 兼容层
三、为什么能互相调用?靠 "桥接",不是 "同一种东西"
OC 调用 Swift
- Xcode 自动生成
模块名-Swift.h,把 Swift 类 / 方法翻译成 OC 能识别的声明 - 但 只有能映射到 OC 类型的才能暴露 (比如
Int→NSInteger,String→NSString) - Swift 特有东西(元组、泛型、可选型)不能直接被 OC 调用
Swift 调用 OC
- Swift 能直接识别 OC 的头文件,自动桥接
NSString↔String、NSArray↔[Any]等 - 本质是:Swift 编译器内置了 OC 语法解析器和类型映射表
一句话:互相能看见,但本质还是两套,中间靠翻译层。
四、回到你最关心的:为什么 Swift 支持重载,OC 不行?
因为语言设计根本不一样:
OC:方法名 = 名字 + 冒号,不管类型
objc
// 这两个是同一个方法!(都是 sum::)
- (int)sum:(int)a :(int)b;
- (NSString *)sum:(NSString *)a :(NSString *)b;
// 编译直接报错:重复定义
- OC 的
@selector只看名字 + 冒号 ,不看参数类型 - 当年设计就没打算支持重载,为了极致动态性(运行时随便改方法)
Swift:方法签名 = 名字 + 参数个数 + 参数类型 + 返回值
swift
// 三个完全不同的签名,共存没问题
func sum(_ a: Int, _ b: Int) -> Int
func sum(_ a: Int, _ b: Int, _ c: Int) -> Int
func sum(_ a: String, _ b: String) -> String
- Swift 编译期严格类型检查,直接按签名选方法
- 你想要的 "按类型识别重载",Swift 从底层就支持
五、总结(直接回答你问题)
- 编译器:前端两套(Clang vs SwiftC),后端一套(LLVM) → 算两个不同编译器
- 语言:完全独立设计,不是 OC 封装版 → 是两个东西
- 兼容:靠桥接层互操作,不是同语法 → 新老代码能共用,但本质不同
- 重载:OC 天生不支持(动态设计),Swift 天生支持(静态设计)
一句话:Swift 和 OC 是 "同根(LLVM)、不同命(语言设计)" 的两个独立语言,靠兼容层绑定在一起。