首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

论沿袭

2012-11-08 
论继承继承是现实系统中非常泛化的一种关系,在人类社会中也非常普遍,比如一个家族。面向对象如果来自对抽象

论继承

继承是现实系统中非常泛化的一种关系,在人类社会中也非常普遍,比如一个家族。面向对象如果来自对抽象数据类型的提升,它只关心数据结构的行为,如果它来自于为维根斯坦的哲学,它表示宇宙中的一个自管理的对象个体。

?

对象存在的前提是封装,封装了结构而开放了行为,开放的行为是对象的外在表现,如果我们希望对象的外在表现可以应场合而变,我们可以进一步把行为抽象,这样便得到接口。

?

如果系统全部用行为接口来交互,是不是声明式编程?

?

对象由它的类型构造,如果类型可以直接构造出对象,那么它是具体类型,如果类型不能直接构造对象,那么它是抽象类型,抽象类型是为了构造具体类型的,而不是为了构造具体对象的,在java语法上,把抽象类型转变为自动类型的过程就是继承,但是设计者并没有禁止从具体类型继承,但是最好的设计是继承的父亲都是抽象类型,最抽象的类型那就是接口。

?

就extends语法而言,还可以用于接口继承接口,这是完全的接口继承,但是类继承即继承接口又继承实现,在java中没有只继承实现的语法 这在ruby,scala,groovy中是不是可以?所以既然继承了接口,那就请保证接口的外在语义。里氏代换原则也是建立在这个基础之上。

?

接口无数据只有行为,如果有数据那是静态和final的,不需维护类的不变量

抽象类型可能有数据又有行为,行为必须保护好类的不变量,开放的数据,必须final,这个开放包括public和protected,最好情况是所有数据全部private,只能开放方法,共同维护了对象状态的一致性的方法需要final,如果不final请注明一致性维护规范,抽象方法是特意留给子类覆盖,这个方法具体化之后将和抽象类型中的其他方法一起构造出对象。

具体类型可能继承自一个抽象类型,或者不继承,也可能继承自一个具体类型,不继承则把握好封装的原则即可,如域必须私有,行为开放,小心被继承,如果被继承,请告知不变量维护规则,如果继承自抽象类型,请覆盖抽象方法即可,如果要覆盖具体方法,那么按照超类得覆盖规范维护好不变量。如果继承自具体类型,可以添加在自己的域,同时保护好自己的域不变量,调用超类行为来维护超类的不变量,如果要覆盖超类行为,请确保超类不变量维护规则。

?

继承中的保护类方法,可能是超类不开放给外界而只开放给子类使用的方法,请只使用而不要覆盖,如果这个保护方法是抽象的,那么它是不开放给外界,而是用来具体化类型的一个内部钩子,请实现它。如果必须覆盖这个一个受保护的具体方法,那么这个方法应该是超类管理不变量的唯一方法,那么也可覆盖,所以超类在设计保护的方法时,要么作为抽象钩子,要么作为不变量唯一约束方法,要么用final来修饰表示只能使用。

?

总结起来:

?

1,接口只表达行为,也可以表达不变数据

2,抽象类型,表达部分不变量,但是行为不完整,需要子类来实现这些行为,他们专为子类设计

3,具体类型,可构造对象,但是也要提防被继承带来的问题

?

继承用语言机制来表达概念泛化,同时引入了多态,也方便的复用了代码,但是复用代码也可以用合成来实现,所以继承设计一定要从概念泛化,多态,代换原则等入手,记住单纯的is a关系并不一定构成继承关系。

?

原则:如果能用合成则尽量用合成,确实不能用合成的地方则仔细设计你的继承,多用final和private为上

?

?

学习Lucene的分词器继承设计:

?

public final class CollationKeyAnalyzer extends Analyzer {  private Collator collator;  public CollationKeyAnalyzer(Collator collator) {    this.collator = collator;  }  @Override  public TokenStream tokenStream(String fieldName, Reader reader) {    TokenStream result = new KeywordTokenizer(reader);    result = new CollationKeyFilter(result, collator);    return result;  }    private class SavedStreams {    Tokenizer source;    TokenStream result;  }    @Override  public TokenStream reusableTokenStream(String fieldName, Reader reader)     throws IOException {        SavedStreams streams = (SavedStreams)getPreviousTokenStream();    if (streams == null) {      streams = new SavedStreams();      streams.source = new KeywordTokenizer(reader);      streams.result = new CollationKeyFilter(streams.source, collator);      setPreviousTokenStream(streams);    } else {      streams.source.reset(reader);    }    return streams.result;  }}
?

?

?

写道

?

The Analyzer-API in Lucene is based on the decorator pattern. Therefore all non-abstract subclasses must be final or their tokenStream and reusableTokenStream implementations must be final! This is checked when Java assertions are enabled.

热点排行