Swift 十二讲 第八章 类型扩展(Extensions)和协
1. Extensions
扩展指的是对已经有的类或者类型添加一些你自己定义的属性,方法。甚至对内建的类型也可以进行扩展。这显然极大的增强了这门语言的威力和灵活性。如下例:
extension Int
{
var a:String{
return "你是个好人"
}
}
var b:Int=2
println(b) //输出2
println(b.a) //输出 "你是个好人"
-
扩展只能添加计算属性,不能添加存储属性。
-
你可以给类添加快捷初始化函数。但是不能给结构体扩展一个委托初始化函数。
-
实例方法的扩展
实例方法的扩展,就是添加一个成员函数。这个成员函数和被创建的实例绑定。例如:
extension Int
{
func a()->String{
return "你是"+String(self)+"个好人"
}
}
var b:Int=20
println(b) //输出20
println(b.a()) //输出“你是20个好人”
如果用mutating关键字,那么实例方法可以修改实例的值。例如:
extension Int
{
mutating func a()
{
self = -self
}
}
var b = 1
println(b) //输出1
b.a()
println(b) //输出-1
类型方法的扩展,前面要加static之类的关键字。这是因为这个方法是和类的定义绑定在一起的。例如:
extension Int
{
static func a()
{
println("坏蛋")
}
}
var b = 20
println(b) //输出20
Int.a() //输出"坏蛋"
- 下标扩展
你还可以给类型添加下标扩展,方便使用。下表扩展和方法扩展的写法非常类似。例如:
extension Int
{
subscript(i:Int)->Int
{
println("下标扩展被调用")
return 123
}
}
var b = 20
println(b[0]) //输出“下标扩展被调用”;输出 123
- Protocols
协议是一组属性,方法,下标等的声明的容器。当你定义一个类的时候,可以指明它需要遵从的协议,然后在类的内部,实现协议规定的那些东西。注意,协议只是个容器,不是实现。所以其实是比类更高一级的描述。描述的是多个类的共同特征。所以协议里的变量,只能声明,不能初始化。方法下标也是如此。例如
protocol a {
var ax:Int = 1
} //Playgroudn会立即报错,"initial value is not allowed here"
了解了协议这个语法的设计思路。它的一些具体写法和用法就可以自然而然的理解了。
- 协议定义的格式为:
protocol 协议名
{//里面写你要定义的东西
}
- 协议使用的格式为:
class 类的名字:[上类的名字] 协议的名字,第二个协议的名字,..等等
如果一个类是从上类继承而来,那么要把上类的名字写在协议名字之前。一个类可以遵从多个协议。
-
协议里面的属性方法等等前面可以加optional 关键字,这用来表示这些元素不一定要在类里面实现。协议里面的属性,后面可以跟{get,set}以表示其为可读也可写的属性。如果只用get,那就是只需要可读。如果只用set,那表示只需要可写。
-
除了类之外,一般的数据类型也可以用extension关键字,来使它遵从一个已经定义了的协议。例如:
protocol a {
func ax()-> Int
}
extension Int: a
{
func ax() -> Int {
println("对不起,你是个好人")
return 0
}
}
var b = 1
b.ax() //输出: 对不起,你是个好人
由上例可以看出,协议是用于多个类的定义的。例如你很多类都要发好人卡,那么定义个协议就可以让你的代码组织结构更好。如果只是一个类需要这个好人卡函数,那就没必要使用协议。
面向对象的一些语言要素,到这一章就基本介绍完了。这里还牵涉到一个更大的话题。一般来说,面向对象的很多特点,例如类继承扩展协议等等都是为了更有组织的进行代码复用。但是,每多一层容器,代码的冗余部分也就越复杂,组织结构也就更复杂。那么,到底在设计项目的结构体系的时候,应不应该用面向对象特性呢?笔者的意见很简单:跟着常识走。如果一个对象或者过程,在现实世界中很容易被拟物,而且后面有很大机会被复用,那设计一个类往往是没错的。例如图形界面元素,按钮。按钮本身就是个物体,然后被图形界面拟物。按钮这个物体显然是有颜色,有大小,有被按后进行什么操作的功能的。所以你设计个类,就不会出错。因为每个程序员脑子里的按钮都是以现实经验为基础的,观念也就比较一致。
但是,例如一些商业逻辑,你采用面向对象的设计思路,就未必是个好办法。这是因为对商业逻辑的理解,人人都可能不同。想想看,买火车票排队这回事,实际上是多么的复杂。这种情况下,笔者认为,不要采用面向对象的方法。不然设计这个体系结构的人走了,你的项目基本就作废了。因为这种情况下设计出来的类协议等等,肯定是个人观点和视角的产物。而人与人之间的交流,往往比一般人想象的要困难的多。
很多计算机书,拿个什么电话号码本,什么矩形长宽,什么员工进出纪录之类的东西,来展示面向对象的方法多么有用,这实际上是不负责任的做法。没有考虑到复杂体系本身的计算开销和维护开销。只考虑了其效果。
当然,你要说我有的是钱。开个项目,写文档的也是第一流人才,或者文档的人比写代码的素质还高。那我就会推荐你用面向对象的元素多一些。
3. 附录,GIT为什么是纯C写的?
(
笔者认为,Linus的观点有些偏颇了。面向对象编程经过几千万人数不清程序验证过的场合,最牢靠的就是图形界面设计。为什么在这个领域这么牢靠?为什么今天图形用户界面部分的编程主流还是面向对象的?我认为主要原因就是图形界面都是拟物的。每个人的集体共识都差不多,所以不会出错。
)
From: Linus Torvalds <torvalds <at> linux-foundation.org>
Subject: Re: [RFC] Convert builin-mailinfo.c to use The Better String Library.
Newsgroups: gmane.comp.version-control.git
Date: 2007-09-06 17:50:28 GMT (2 years, 14 weeks, 16 hours and 36 minutes ago)
On Wed, 5 Sep 2007, Dmitry Kakurin wrote:
When I first looked at Git source code two things struck me as odd:
- Pure C as opposed to C++. No idea why. Please don't talk about portability,
it's BS.
下面是Linus的回答:
YOU are full of bullshit.
C++ is a horrible language. It's made more horrible by the fact that a lot
of substandard programmers use it, to the point where it's much much
easier to generate total and utter crap with it. Quite frankly, even if
the choice of C were to do nothing but keep the C++ programmers out,
that in itself would be a huge reason to use C.
In other words: the choice of C is the only sane choice. I know Miles
Bader jokingly said "to piss you off", but it's actually true. I've come
to the conclusion that any programmer that would prefer the project to be
in C++ over C is likely a programmer that I really would prefer to piss
off, so that he doesn't come and screw up any project I'm involved with.
C++ leads to really really bad design choices. You invariably start using
the "nice" library features of the language like STL and Boost and other
total and utter crap, that may "help" you program, but causes:
- infinite amounts of pain when they don't work (and anybody who tells me
that STL and especially Boost are stable and portable is just so full
of BS that it's not even funny) - inefficient abstracted programming models where two years down the road
you notice that some abstraction wasn't very efficient, but now all
your code depends on all the nice object models around it, and you
cannot fix it without rewriting your app.
In other words, the only way to do good, efficient, and system-level and
portable C++ ends up to limit yourself to all the things that are
basically available in C. And limiting your project to C means that people
don't screw that up, and also means that you get a lot of programmers that
do actually understand low-level issues and don't screw things up with any
idiotic "object model" crap.
So I'm sorry, but for something like git, where efficiency was a primary
objective, the "advantages" of C++ is just a huge mistake. The fact that
we also piss off people who cannot see that is just a big additional
advantage.
If you want a VCS that is written in C++, go play with Monotone. Really.
They use a "real database". They use "nice object-oriented libraries".
They use "nice C++ abstractions". And quite frankly, as a result of all
these design decisions that sound so appealing to some CS people, the end
result is a horrible and unmaintainable mess.
But I'm sure you'd like it more than git.
Linus