zoukankan      html  css  js  c++  java
  • 开源搜索框架Lucene学习之分词器(3)——通过分词器源码学习抽象方法与虚方法的区别

       在我研读分词器源码的过程中,又碰到了以前还未完全弄明白的抽象方法与虚方法。下面我将结合源码里面的内容,重新来学习一些抽象方法与虚方法的区别。

       下面是分词器模块中的一部分类的关系图。

    image

    TokenStream类是所有类的父类。TokenStream类里面有两个方法,看下面的代码:

    abstract public class TokenStream
    {
        ///<summary>
        ///返回语汇单元流中的下一个词元,或者是空,也就是结束,返回EOS
        ///Returns the next token in the stream, or null at EOS. 
        ///</summary>
        abstract public Token Next();
     
        ///<summary>
        ///释放语汇单元流所使用的资源
        ///</summary>
        public virtual void Close()
        {
        }
    }

    Next是一个抽象方法,Close是一个虚方法。通过上面的代码,我们就可以看出一些区别:

    抽象方法:

    1.以abstract修饰,abstract在Public的前面。没有方法体,在小括号后面直接跟一分号就结束,没有大括号。

    2.有抽象方法的类一定是抽象类,我们可以看到TokenStream类是一个抽象的类。但抽象类中可以有非抽象的方法,比如Close就是非抽象的方法。

    虚方法:

    1.以virtual修饰,virtual在Public的后面。有方法体,在小括号的后面跟着一对大括号。此大括号里可以有方法的实现,也可以没有,此处为没有实现。

    我们再来看看TokenStream类的一个子类TokenFilter,它的代码如下:

    abstract public class TokenFilter : TokenStream
    {
        ///<summary>
        ///需要传过来的处理的TokenStream
        ///The source of tokens for this filter. 
        ///</summary>
        protected TokenStream input;
     
        ///<summary> Close the input TokenStream. </summary>
        public override void Close()
        {
            input.Close();
        }

         可以看到此类实现了虚方法Close,但是却找不到抽象方法Next的踪迹。这是为什么呢,不是说子类一定要实现抽象方法,不一定要实现虚方法的吗,难道有错?。我们再来看看TokenFilter这个类,需要注意,它前面有一个abstract来修饰,这说明它是一个抽象类。所以一切就明白了。确切的来说:

         非抽象的子类一定要实现父类的抽象方法。也就是子类一定要实现父类的抽象方法,如果没有实现,那么这个子类一定也是个抽象类,那么父类的抽象方法就由这个子类的非抽象子类去实现。

         子类不一定要实现父类的虚方法,不管这个类是不是抽象类。

          我们再来看看TokenFilter的子类LowerCaseFilter类,它的代码如下:

    public class LowerCaseFilter : TokenFilter
    {
        /// <summary>
        /// Initializes a new instance of the LowerCaseFilter class.
        /// </summary>
        /// <param name="ts">Token stream to read from.</param>
        public LowerCaseFilter(TokenStream ts)
        {
            input = ts;
        }
     
        /// <summary>
        /// Returns the next token from the stream.
        /// </summary>
        /// <returns>The next token or null if EOS.</returns>
        public override Token Next()
        {
            Token t = input.Next();
     
            if (t == null)
                return null;
     
            t.TermText = t.TermText.ToLower();
     
            return t;
        }
    }
    可以看到这个类不是抽象类,所以我们看到它实现了TokenStream中的抽象方法Next,但是它并没有实现虚方法Close。还有一点需要注意的是不管是抽象方法还是虚方法,子类在实现这个方法的时候,需要在前面加上关键字override。

    因为抽象方法是强制要求非抽象子类必须实现,所以不能用Sealed来修饰抽象方法,因为Sealed表示这个方法不能被继承,而抽象方法又必须需要子类来实现。

         最后来总结一下两者的区别:

         1.抽象方法与虚方法的定义方式不同,抽象方法是用abstract来修饰,虚方法是用virtual修饰。抽象方法是小括号后面加一个分号,而虚方法是小括号后面还有大括号,大括号里面可以有方法的实现内容,也可以没有。

         2.有抽象方法的类一定是抽象类,抽象类中的方法不一定非要是抽象方法,也可以有其他的非抽象方法。而普通类中也可以有虚方法求。

         3.非抽象的子类一定要实现父类中的抽象方法,而对于虚方法,子类可以实现,也可以不实现。

         4.抽象方法不能与Sealed关键字一起使用。

         5.子类实现抽象方法或虚方法,需要在前面加上override关键字。

  • 相关阅读:
    Socket编程
    jdbc03 使用servlet实现
    el和jstl
    java03变量和基本数据类型
    java02
    ssh整合
    U1总结
    多线程
    spring07 JDBC
    cocos2dx中的三种基本的数据类型
  • 原文地址:https://www.cnblogs.com/xiaoxiangfeizi/p/2312306.html
Copyright © 2011-2022 走看看