接口、抽象类问题

本文探讨了抽象类和接口在面向对象编程中的角色,包括它们的共同点和区别。抽象类可以包含字段、属性和方法实现,而接口仅能定义方法、属性等。接口可以被多重实现,抽象类只能被单一继承。文章建议在对象间差异较大但共享行为时使用接口,而在具有明显共性的对象间使用抽象类。同时强调了面向接口编程的重要性。
摘要由CSDN通过智能技术生成

简述抽象类和接口的区别是常见的一个面试题,如下:

 public abstract class A  //抽象类
    {
        public int num = 5;//抽象类包含字段
        public int Num     //抽象类包含属性
        {
            get { return num; }
            set { num = value; }
        }
        public virtual int getNum() //抽象类包含虚方法
        {
            return Num + num;
        }
        public void  A1()   //抽象类包含一般方法
        {
            string q="大黄蜂!";
            Console.WriteLine(q);
        }
        public abstract int A2();
    }

上述中可以看出抽象类中包含字段,属性,虚方法,也可以实现一般方法,抽象类可以带方法体

    public interface IC     //接口 
    {
          int getSuper();  //定义getSuper方法
    }

从接口中来看,可以定义方法、包含属性,当然也可以拥有事件和索引器,且所有默认修饰符问public,接口不带方法体

    public class B : A, IC  //B 继承抽象类A,继承接口C
    {
        public int getSuper()   //实现接口C中getSuper方法
        {
            return num + Num + 100;
        }
        public override int A2() //实现抽象类A中的抽象A2方法
        {
            //throw new NotImplementedException();
            return num + Num + 200;
        }
    }
        static void Main(string[] args)
        {
            B b = new B();
            //从类B中调用抽象类A中A1方法体
            b.A1();          
            //从类B中调用抽象类A中num字段
            Console.WriteLine(b.num);
            //从类B中调用抽象类A中Num属性
            Console.WriteLine(b.Num);      
            //从类B中调用抽象类A中getNum虚方法
            Console.WriteLine(b.getNum());   
            //从类B中调用接口C中的getSuper方法名,
            Console.WriteLine(b.getSuper()); 
             //从类B中调用抽象类A中的抽象方法A1
            Console.WriteLine(b.A2());      
            Console.ReadLine();
        }
    }

可以看出来一般基类可以同时继承抽象类和接口,但是抽象类只能继承一个,接口可以继承多个,之间用逗号隔开。
基类如果继承接口就必须实现接口中所有的方法,属性等;
如果继承抽象类可以直接调用抽象类的方法体,也可以调用方法名自己实现,且抽象类中所有定义的字段,属性,方法名等可以不全部实现。

总结:
1、抽象类和接口的共同点:
(1) 都可以被继承
(2) 都不能被实例化
(3) 都可以包含方法声明
(4) 派生类必须实现未实现的方法。
2、抽象类和接口的区别:
(1) 抽象基类可以定义字段、属性、方法实现。接口只能定义属性、索引器、事件、和方法声明,不能包含字段。
(2) 抽象类是一个不完整的类,需要进一步细化,而接口是一个行为规范。微软的自定义接口总是后带able字段,证明其是表述一类“我能做。。。”
(3) 接口可以被多重实现,抽象类只能被单一继承
(4) 抽象类更多的是定义在一系列紧密相关的类间,而接口大多数是关系疏松但都实现某一功能的类中
(5) 抽象类是从一系列相关对象中抽象出来的概念, 因此反映的是事物的内部共性;接口是为了满足外部调用而定义的一个功能约定, 因此反映的是事物的外部特性
(6) 接口基本上不具备继承的任何具体特点,它仅仅承诺了能够调用的方法
(7) 接口可以用于支持回调,而继承并不具备这个特点
(8) 抽象类实现的具体方法默认为虚的,但实现接口的类中的接口方法却默认为非虚的,当然您也可以声明为虚的
(9) 如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法。

那在什么时候可以使用接口或者是抽象类呢?
如果给你三个对象分别是人、鱼、青蛙,让你为他们设计个基类来概括它们之间的联系,那么首先给你的感觉肯定是它们个体间的差异性较大,很难抽象出共性,然而若让你概括他们行为之间的共性,你可能想了想会意识到他们都会游泳,只不过是游泳方式迥异。那么这时你就应当考虑使用接口而不是抽象基类,原因有三条:
1. 个性大于共性。
2. 差异较大的个性间具有某些相同的行为。
3. 相同行为的实现方式有较大区别。

这时再给你三个对象,分别是鲫鱼、鲤鱼、金鱼,仍然让你设计基类来概括它们之间的联系,那么你第一个意识到的肯定是它们都属于鱼类,其次是他们游泳的方式可能稍有差异,这时就应当使用抽象基类而不是接口,对比着上面的例子,原因也有三条:
1. 共性大于个性
2. 共性相同的个体间必然具有相同的属性与行为
3. 相同行为的实现方式具有一定区别

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

规则与场合
1.请记住,面向对象思想的一个最重要的原则就是:面向接口编程。
2.借助接口和抽象类,23个设计模式中的很多思想被巧妙的实现了,我认为其精髓简单说来就是:面向抽象编程。
3.抽象类应主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能。
4.接口着重于CAN-DO关系类型,而抽象类则偏重于IS-A式的关系;
5.接口多定义对象的行为;抽象类多定义对象的属性;
6.接口定义可以使用public、protected、internal 和private修饰符,但是几乎所有的接口都定义为public,原因就不必多说了。
7.“接口不变”,是应该考虑的重要因素。所以,在由接口增加扩展时,应该增加新的接口,而不能更改现有接口。
8.尽量将接口设计成功能单一的功能块,以.NET Framework为例,IDisposable、IDisposable、IComparable、IEquatable、IEnumerable等都只包含一个公共方法。
9.接口名称前面的大写字母“I”是一个约定,正如字段名以下划线开头一样,请坚持这些原则。
10.在接口中,所有的方法都默认为public。
11.如果预计会出现版本问题,可以创建“抽象类”。例如,创建了狗(Dog)、鸡(Chicken)和鸭(Duck),那么应该考虑抽象出动物(Animal)来应对以后可能出现风马牛的事情。而向接口中添加新成员则会强制要求修改所有派生类,并重新编译,所以版本式的问题最好以抽象类来实现。
12.从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实实现。
13.对抽象类不能使用new关键字,也不能被密封,原因是抽象类不能被实例化。
14.在抽象方法声明中不能使用 static 或 virtual 修饰符。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值