关于面向对象的一些思考

  适才在写python程序,写一个对象的集合容器类,纠结要不要实现迭代器方法来允许for in语句。突然发现,for a in obj和for a in obj.l 给人很大的不同感。我并没有一下子得到明确的思绪(这也不构成问题,仅仅是一个“问题”),想到在哲学群里的争论和一些以前的思考,决定写一篇博客。

  其实写到这里,我已经有些思路了,那就是python不隐藏属性,做不到很好的封装——不过更多地,我也没有刻意区分过“状态”和“属性”(也许“字段”和“属性”对某些人更好些),即一个对象中保存的值在机能上的意义。如果实现迭代方法,那么该类对外就和列表没什么关系。而假如用obj.l的方式,那么这个类仅仅是“列表的容器“(而非自定义对象的容器),列表这个本该多余的概念始终是暴露的,它应该作为隐式的“状态”,而不是供外部访问的“属性”。——在语言层面,python的对象只有属性,但(我觉得)也许某些程序员……会下意识地区分二者,并使用python的“假私有属性”特性——用双下划线开头的名称命名(用作状态的)属性。


  而之前还有一次对于面向对象的思考,和“模板继承”相关。python的format函数可以很方便地作为模板,假如我们需要一个网页模板——即用来生成只有少量几处不同的字符串,我们可以用 待format的 字符串来表示它,然后传入各个值,比如:

template = "<h1>Good {time}, {name}!</h1>"
print(template.format(time="night",name="Amy"))

  而“模板继承”引出了哲学问题。假如:

template2 = "<h1>Good night, {name}!</h1>"

  这个模板显然“应当”从之前的模板“继承”而来。而实现这个“继承”,可以仅仅扩展format函数,添加这样一条规则:

  • 新的format函数对于不匹配的项,不执行替换

  我们可以预计它的行为:

>>> "<h1>Good {time}, {name}!</h1>".format(time="night")
"<h1>Good night, {name}!</h1>"

  这个新的format函数就很有趣了,它拥有普通format的功能!也就是说,假如说普通format“可以将一个模板实例化”,那么对于新的format,“它既可以将一个模板实例化,也可以将一个模板继承出新模板”。这时候我开始质疑自己了,究竟什么是实例化和继承?

  另外这里给出一个新format函数的粗略实现(笑):

def new_format(s,**d):
    class D:
        def __init__(self,d):self.__d = d
        def __getattr__(self,s):return self.__d.get(s,'{'+s+'}')
    s_ = '{0.'.join(s.split('{'))
    return s_.format(D(d))

template = "<h1>Good {time}, {name}!</h1>"  # test
print(new_format(template,time="night",name="Amy"))
print(new_format(template,time="night"))

  我想到了另一个问题:一个无需替换的字符串,固然可以看成一个实例,但何尝不也是一个类呢?这个派生出的类,把基类的初始化参数填满了,不需要其他参数了而已。——接触过偏函数,甚至柯里化的朋友,可以借此比对一下。

  我在面向对象有关的书里,看到过(大致)这样的例子:“水果是一个类,而苹果,梨等等是水果类派生出的实例。”仔细想想便会发现,实际中苹果、梨也是类,而具体的某个苹果,某个梨才“称得上”实例——但是倒不是我批驳这个举例,实例化就是个骗局!(笑)试想在计算机中,我们是如何描述一个“实例”的?一些具体的数据 ,是吧?但是,从哲学上说,任意多的描述都不能指定出一个具体的东西,它依然是一堆描述,而一堆描述正是指定了一个“类”!

  从来都没有实例化,只有继承。——然而学编程不须学哲学,姑且相信实例化并不造成任何实质问题,除了在极少情况下面对“苹果是对象还是类”时会有些困惑……

  不过很多情况下,类已经写死在语言里了。只能说,把我们要泛化的一层看成实例化即可……或者用lua的面向对象系统,或者根本不使用现成的类型系统来表示实际的类(Unity的ECS模型似乎有这种哲学)

  但是从字符串到类,这个比对妥当么?类的继承让功能越来越多,字符串和偏函数却让功能越来越少。类的继承添加了功能。

  不过仔细想想也不矛盾,添加功能也“使自由度变低了”。使用一个类在逻辑上也不能使用子类的功能。

  ………………(我该在自己的语言里实现类来体验一下)


  还有一次思考,是在和别人百般解释不清某个抽象概念,感慨自然语言之其妙。请看如下表述:
  “苹果可以吃

  是不是很奇妙?“苹果”是一个类,但可以吃的东西自然是某个实例(现实中的“实例”还是比较妥的),而此表述没人会误会。但是——

  “梦是假的

  我是由怎样的表述而理解“梦本身是真的”这一情况的?我该如何表达?

  逻辑果然不是人该干的事。

(2018-8-12 于地球)(完)

猜你喜欢

转载自blog.51cto.com/13535617/2158462