数学上,集合论可以描述一切公理,虽然惨遭“罗素悖论”的狙击,但是还是有解决方案的,至少在不考虑悖论的情况下,我们可以认为它是“完美”的。
集合的概念,想必大家都很熟悉。
{ x | 颜色是红色的 } 是一个集合, { 星期1,星期2 ... 星期日 } 也是一个集合。
如果我们把集合看作一个类的话,后者显然是一个枚举,那么前者呢?前者是这样:
class Foo {
红色 get颜色();
}
这代表一个描述,描述了一类对象的特征,
显然 我们刻画一个集合,除了枚举它所有成员以外,还可以刻画这个集合中所有成员的共性,这是描述一个集合的2种基本方式。
前面刚刚讲过,我们最基本的单元是四元组,
一个四元组代表一条属性。红色 ObjFoo.get颜色(); 是一个四元组 [ ObjFoo, 颜色,void, 红色 ]。
那么在用描述方式刻画集合时,一个集合 显然等价于 一组描述, 也就是说 集合 等价于 一个或多个四元组。
我们可以这么定义汽车的集合(汽车有发动机,汽车可以用档位作为初始参数启动):
{
[汽车,发动机,void,有]
[汽车,启动,档位, void]
}
如果我们抽象出一个交通工具的集合:
{ [交通工具,启动,档位,void]
[交通工具, 停止,void,void]
}
从这里我们可以看出一种集合和类的对应关系。如果方法 对应 四元组,那么一个包含多个四元组的集合,也就明显可以映射到一个包含多个方法的类。(前面我们已经说了,属性可以看作是方法)
那么考虑到继承关系汽车的集合或许可以改为这样:
{
[汽车,发动机,void,有]
[交通工具,启动,档位,void]
[交通工具,停止,void,void]
}
那么这种继承用集合表述是什么呢?
我们可以很容易的得到这样的关系:汽车是交通工具的子类,汽车是交通工具的子集。子集即子类。
子集是什么?子集要求集合中的元素拥有超集的全部属性(四元组),并且还拥有自己独特的属性,也就是子集扩展了超集的四元组。
从程序语言的角度来说,子类要求扩展父类的全部方法,并可能有自己独特的方法,在这一点上,集合和OO语言似乎完美契合了。
假设父类为:
Class Father { someobj somemethod(someobj obj) }
则子类一定为
Class Child { someobj somemethod(someobj obj); ....... }
让我们思考下面两个集合,
A: 比鸟快
B:比动物快
显然因为鸟是动物的子集,所以B是A的子集(比动物快一定比鸟快),按照我们子集即子类的思路, 那么B也应该是A的子类,从四元组的角度看如果A有四元组
[FooA, 速度比,鸟,快],那么B就有四元组
[FooB, 速度比,动物,快]
我们都知道,编程里面对于方法的继承有重写(override)机制,但是上面这种例子跟重写还不完全一样,它不仅可能改变了方法的实现,还改变了方法的入参。
我们从集合中看出,如果 方法A(四元组)的入参是 是 方法B(四元组) 的子类(子集 ),那么方法A可以看作方法B的 父方法。 因为四元组A所代表的集合是四元组B所代表的集合的超集。
事实上,如果用泛型举例,假设有类
Class A {
Fast than(T2 param);
}
类
Class B {
Fast than(T1 param);
}
那么B可以为A的子类。在C#中,这种特性叫做 反变
例如
Class SayHello {
public String saySomeThing(T param) {
return param + "hello";
}
}
SayHello manSayHello;
SayHello peopleSayHello;
按照我们之前的结论,因为入参 man是people的子类,那么SayHello>,是SayHello>的父类 ,
如果我们进行类型转换
SayHello> manFromPeopleSayHello = (SayHello>)peopleSayHello;
manFromPeopleSayHello.saySomeThing(man);
会发生什么?
显然由于man是people的子类, 所以peopleSayHello的方法 public String saySomeThing(People param) 调用在这里可以通过编译,
其次其实现:
public String saySomeThing(Man param) {
return param + "hello";
}
完全可以无错误的执行,返回 "manhello" 这样的值。
如果我们反着来:
SayHello peopleFromManSayHello = (SayHello>)peopleSayHello;
peopleFromManSayHello.saySomeThing(people);
会发生什么?
由于people不能转化为man,所以调用错误。
这里,泛型只是为了说明这种情况的特例,也就是说当实现相同(只是参数不同)时,如果入参呈现 父子 关系,那么拥有函数的类可以呈现 子父 关系。
如果不是泛型的话,也可以这么做,因为类可以override,当参数满足要求时,我们也可以override,人工保证这个继承关系。
四元组的继承关系,可以发明一个符号来标识它,例如:
[id = "thantest" fooobj than man fast]
[id = "thantestsub" extend = "thantest" fooobj than people fast]
那么集合也呈现父子关系
{ id="foo" { [ ref="thantest" ] } }
{ id="foosub" { [ ref="thantestsub" ] } }
当然,在我们在传统继承关系中,一个方法重载另一个方法,是不改变入参的,这实际是上面例子的一种特殊情况。总结一下我们可以得出这样的结论:
当集合A是集合B的子集,或者等于集合B时,如果四元组A的域是A, 四元组B的域是B,那么四元组A是四元组B的父四元组,在编程中如果这两个四元组代表的函数实现相同,则四元组A代表的方法A可以看作四元组B代表的方法B的父方法的定义(根据实现方法A也许不是方法B的父方法 ,如果它们实现相同,例如泛型,则方法A是方法B的父方
法 )。
类似的,让我们思考返回值的情况。例如
[FooA, 速度比,鸟,快] A
[FooB, 速度比,鸟,快又稳] B
显然,由于快又稳是快的子集,那么B是A的子四元组。泛型的例子也依然有效,这在C#里称为协变
类似的,我们有结论(注意与上面的结论父子关系反着,域变为值):
当集合A是集合B的子集,或者等于集合B时,如果四元组A的值是A, 四元组B的值是B,那么四元组A是四元组B的子四元组,在编程中如果这两个四元组代表的函数实现相同,则四元组A代表的方法A可以看作四元组B代表的方法B的子方法的定义(根据实现方法A也许不是方法B的子方法 ,如果它们实现相同,例如泛型,则方法A是方法B的子方
法 )。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/26899445/viewspace-1376509/
,如需转载,请注明出处,否则将追究法律责任。