建议学习了Julia的基本语法(以及C++和Python的基本语法)再阅读这篇文章。这个专栏的大部分文章都不是面向初学者的。
Julia里没有class,没有继承(inheritance)到底要怎么设计程序?最近几个月里常常有人问我,然后也review过一些代码发现因为不知道要怎么写,最后都变成过程式的写法了。
首先,Julia并没有抛弃对象(object)这个概念,没有class这样的结构不代表没有object,Julia里从简单的值(整数,浮点数等等)到复杂的类型的实例(instance),类型本身,再到Julia自己的代码表达式全部都是对象。或者简单的讲,Julia里一个object是某个类型(type)的实例。
但是和带有class的语言不同的是,我们在设计代码的时候思路不同。Julia里我们围绕方法设计代码,有人也称为method oriented programming,而非围绕对象设计代码。用某个算符举个例子。我们假设有这样一类算符:每个算符都有一个矩阵形式,然后每个算符都可以通过一个apply方法作用在一个向量上,作用的方法是一样的就是按照矩阵的大小把这个向量reshape成一个矩阵,然后进行矩阵乘法。
在Python这样使用class模型的语言里会这样写
class Operator(object):
def __init__(self):
pass
def apply(self, vector):
U = self.mat()
v = vector.reshape((len(vector) // U.shape[0], U.shape[0]))
return np.matmul(v, U)
def mat(self):
raise NotImplementedError
class OpA(Operator):
def mat(self):
return np.random.rand(2, 2)
class OpB(Operator):
def mat(self):
return np.eye(4)
我们首先会定义一个矩阵对象,然后思考这个矩阵对象可以有什么方法,可以做什么事情。比如这样的算符都可以使用apply这个方法,然后都有一个对应的矩阵。所以我们先声明Operator这个对象,实现一个比较一般的apply方法,再让其它类型的算符继承它,这样我们只要实现不同类型所对应的矩阵就好了。
但是在Julia里,我们更加关心的是能干什么,而不是谁能干什么。所以我们先声明apply这个函数(generic function),不管是谁,反正有这么一种方法。
function apply end
接下来我们知道,对于某一类算符,这种方法有一种通用的实现,所以我们对这一类算符定义一个抽象类型
abstract type AbstractOperator end
function apply(op::AbstractOpera