• 抽象类和接口的异同


    本文在文字说明的时候将不会举例,在文章写完后,在列出整个例子

    一、抽象类:(abstract class)
        抽象类是特殊的类,只是不能被实例化;除此以外,具有类的其他特性;重要的是抽象类可以包括抽象方法,这是普通类所不能的。抽象方法只能声明于抽象类中,且不包含任何实现,派生类必须覆盖它们。另外,抽象类可以派生自一个抽象类,可以覆盖基类的抽象方法也可以不覆盖,如果不覆盖,则其派生类必须覆盖它们。抽象类不能被密封。 
     
      抽象类中virtual和abstract的异同
      相同点:两者是为了实现多态,都可以重写。
                对象都可以不调用子类的该方法。
      不同点:virtual在基类中必须有方法的实现,abstract必须只有方法的声明
                virtual在子类中可以不重写;abstract必须在子类中重写
     

    二、接口:(interface)

      接口是引用类型的,类似于类

      接口有如下特性:接口除了可以包含方法之外,还可以包含属性、索引器、事件,而且这些成员都被定义为公有的。除此之外,不能包含任何其他的成员,例如:常量、域、构造函数、析构函数、静态成员。一个类可以直接继承多个接口,但只能直接继承一个类(包括抽象类)。

      使用C#接口应注意几个问题:

      1、C#中的接口是独立于类来定义的。这与 C++模型是对立的,在 C++中接口实际上就是抽象基类。

      2、接口和类都可以继承多个接口。

      3、类可以继承一个基类,接口根本不能继承类。C#的简化接口模型有助于加快应用程序的开发。

      4、一个接口定义一个只有抽象成员的引用类型。C#中一个接口实际所做的,仅仅只存在着方法标志,但根本就没有执行代码。这就暗示了不能实例化一个接口,只能实例化一个派生自该接口的对象。

      5、接口可以定义方法、属性和索引。所以,对比一个类,接口的特殊性是:当定义一个类时,可以派生自多重接口,而你只能可以从仅有的一个类派生。

      6、好的接口定义应该是具有专一功能性的,而不是多功能的,否则造成接口污染。如果一个类只是实现了这个接口的中一个功能,而不得不去实现接口中的其他方法,就叫接口污染。

      7、如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法.

     

    三、接口和抽象类的相似之处有四点:
           1、不能实例化,但可以声明它们的变量 ;
           2、包含未实现的方法声明;
           3、派生类必须实现未实现的方法,抽象类是抽象方法,接口则是所有成员(不仅是方法包括其他成员);

           4、接着通过这些变量来使用这些类型的成员,但不能直接访问派生对象的其它成员。

    四、抽象类和接口的区别:

      1、派生类只能继承一个基类,即只能直接继承一个抽象类(但可以用一个继承链包含多个抽象类)。相反,类可以使用任意多个接口。

      2、抽象类可以拥有抽象成员和非抽象成员。

        抽象成员:没有代码体,且必须在派生类中执行,否则派生类本身必须也是抽象的。

        非抽象成员:拥有代码体,也可以是虚拟的,这样就可以在派生类中重写。

      3、接口成员必须都在使用接口的类上执行——它们没有代码体。

      4、接口成员被定义为公共的,但抽象类的成员也可以是私有的、受保护的、内部的或受保护的内部成员(其中受保护的内部成员只能在应用程序的代码或派生类中访问)。此外,接口不能包含字段、构造函数、析构函数、静态成员或常量。

      5、类是对对象的抽象,可以把抽象类理解为把类当作对象,抽象成的类叫做抽象类.而接口只是一个行为的规范或规定,微软的自定义接口总是后带able字段,证明其是表述一类类“我能做......”。抽象类更多的是定义在一系列紧密相关的类间,而接口大多数是关系疏松但都实现某一功能的类中.   

     

    一些专家看法:

        dunai认为:抽象类是提取具体类的公因式,而接口是为了将一些不相关的类“杂凑”成一个共同的群体。至于他们在各个语言中的句法,语言细节并不是我关心的重点。

        Artech认为:所代码共用和可扩展性考虑,尽量使用Abstract Class。当然接口在其他方面的优势,我认为也不可忽视。

        shenfx认为:当在差异较大的对象间寻求功能上的共性时,使用接口;当在共性较多的对象间寻求功能上的差异时,使用抽象基类。

     

    最后,有关C#接口和抽象类的学习,MSDN的建议:

        如果预计要创建组件的多个版本,则创建抽象类。抽象类提供简单易行的方法来控制组件版本。通过更新基类,所有继承类都随更改自动更新。另一方面,接口一旦创建就不能更改。如果需要接口的新版本,必须创建一个全新的接口。

        如果创建的功能将在大范围的全异对象间使用,则使用接口。抽象类应主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能。

        如果要设计小而简练的功能块,则使用接口。如果要设计大的功能单元,则使用抽象类。

        如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类。抽象类允许部分实现类,而接口不包含任何成员的实现。

     

    网上的一个比喻:
      1.飞机会飞,鸟会飞,他们都继承了同一个接口“飞”;但是F22属于飞机抽象类,鸽子属于鸟抽象类。
      2. 就像铁门木门都是门(抽象类),你想要个门我给不了(不能实例化),但我可以给你个具体的铁门或木门(多态);而且只能是门,你不能说它是窗(单继承);一个门可以有锁(接口)也可以有门铃(多实现)。 门(抽象类)定义了你是什么,接口(锁)规定了你能做什么(一个接口最好只能做一件事,你不能要求锁也能发出声音吧(接口污染))。

     

    例子:

      1、新建一个控制台应用程序ClassTest,新建类Animals

    public abstract class Animals
    {
            protected string _name;
            //声明抽象属性
            public abstract string Name { get; }
            //声明抽象方法
            public abstract void Show();
            //实现虚方法
            public virtual void MakeVoice()
            {
                Console.WriteLine("All animals can make voice.");
            }
            //实现一般的方法
            public void Sleep()
            {
                Console.WriteLine("All the animals need to sleep.");
            }
    }

      2、新建一个接口IAction

    public interface IAction
    {
          void Move();
    }

      3、新建一个Duck类:

        public class Duck : Animals, IAction {
            public Duck(string name)
            {
                _name = name;
            }
            //重写抽象属性
            public override string Name
            {
                get
                {
                    return _name;
                }
            }
            //重写抽象方法,抽象方法必须重写
            public override void Show()
            {
                Console.WriteLine(_name + " is showing for you!");
            }
            //重写虚方法
            public override void MakeVoice()
            {
                Console.WriteLine("I am a duck,ga....ga....");
            }
            //实现接口方法
            public void Move()
            {
                Console.WriteLine("Duck also can swim.");
            }
        }

      4、新建一个Dog类:

        public class Dog : Animals, IAction {
            public Dog(string name)
            {
                _name = name;
            }
         //重写抽象属性
    public override string Name { get { return _name; } }
         //重写抽象方法,抽象方法必须重写
    public override void Show() { Console.WriteLine(_name + " is showing for you!"); }
    //实现接口方法
    public void Move() { Console.WriteLine("Dog also can run."); } }

      5、在Main函数中写代码:

            static void Main(string[] args)
            {
                Animals duck=new Duck("Duck");
                Console.WriteLine(duck.Name);
                duck.Sleep();
                duck.Show();
                duck.MakeVoice();//调用重写后的虚方法
                Console.WriteLine();
    
                Animals dog=new Dog("Dog");
                Console.WriteLine(dog.Name);
                dog.Sleep();
                dog.Show();
                dog.MakeVoice();//直接调用基类虚方法
                Console.WriteLine();
    
                Dog dog1=new Dog("Dog1");
                Console.WriteLine(dog1.Name);
                dog1.Show();
                Console.WriteLine();
    
                IAction dog2=new Dog("A big dog");
                dog2.Move();
                Console.WriteLine();
            }

      6、执行结果如下:

     

     

     

    参考资料:

    《C#语言参考》

    《C#完全手册》

    http://www.cnblogs.com/bear-study-hard/archive/2006/01/09/313673.html

    http://blog.csdn.net/gz2008gz/article/details/4365971

     

  • 相关阅读:
    Atitit.eclise的ide特性-------abt 编译
    Atitit.eclise的ide特性-------abt 编译
    Atitit python3.0 3.3 3.5 3.6 新特性 Python2.7新特性1Python 3_x 新特性1python3.4新特性1python3.5新特性1值得关注的新特性1Python3.6新特性2  Python2.7新特性Python 2.7的新特性
    Atitit python3.0 3.3 3.5 3.6 新特性 Python2.7新特性1Python 3_x 新特性1python3.4新特性1python3.5新特性1值得关注的新特性1Pyth
    Atitit intellij idea的使用总结attilax
    Atitit.eclipse 4.3 4.4  4.5 4.6新特性
    Atitit.eclipse 4.3 4.4  4.5 4.6新特性
    Atitit.eclipse 4.3 4.4  4.5 4.6新特性
    Atitit 软件国际化原理与概论
    Atitit 软件国际化原理与概论
  • 原文地址:https://www.cnblogs.com/huangbx/p/2625822.html
Copyright © 2020-2023  润新知