接口和抽象类有什么区别

本文详细阐述了抽象类与接口的概念及其在软件开发中的应用场景,包括它们的特点、使用场合及其实现方式,帮助读者理解两者之间的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简单来说,
接口是公开的,里面不能有私有的方法或变量,是用于让别人使用的,而抽象类是可以有私有方法或私有变量的,

另外,实现接口的一定要实现接口里定义的所有方法,而实现抽象类可以有选择地重写需要用到的方法,一般的应用里,最顶级的是接口,然后是抽象类实现接口,最后才到具体类实现。

也可以理解为 :接口用来解耦和,回调,在项目开发初,抽象类用来定原型,接口用来确定功能


抽象方法是必须实现的方法。就象动物都要呼吸。但是鱼用鳃呼吸,猪用肺呼吸。动物类要有呼吸方法。怎么呼吸就是子类的事了。
现在有很多讨论和建议提倡用interface代替abstract类,两者从理论上可以做一般性的混用,但是在实际应用中,他们还是有一定区别的。
抽象类一般作为公共的父类为子类的扩展提供基础,这里的扩展包括了属性上和行为上的。而接口一般来说不考虑属性,只考虑方法,使得子类可以自由的填补或者扩展接口所定义的方法,就像JAVA王子所说的事件中的适配器就是一个很好的应用。
用一个简单的例子,比如说一个教师,我们把它作为一个抽象类,有自己的属性,比如说年龄,教育程度,教师编号等等,而教师也是分很多种类的,我们就可以继承教师类而扩展特有的种类属性,而普遍属性已经直接继承了下来。
而接口呢~还是拿教师做例子,教师的行为很多,除了和普通人相同的以外,还有职业相关的行为,比如改考卷,讲课等等,我们把这些行为定义成无body的方法,作为一个集合,它是一个interface。而教师张三李四的各自行为特点又有不同,那么他们就可以扩展自己的行为body。从这点意义上来说, interface偏重于行为。
总之,在许多情况下,接口确实可以代替抽象类,如果你不需要刻意表达属性上的继承的话。


PS:耦合这个东西我还是画个图吧 看图比较明显
这里写图片描述
这里写图片描述
总结几句话来说:

1、抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。

2、抽象类要被子类继承,接口要被类实现。

3、接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现

4、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。

5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。

6、抽象方法只能申明,不能实现,接口是设计的结果 ,抽象类是重构的结果

7、抽象类里可以没有抽象方法

8、如果一个类里有抽象方法,那么这个类只能是抽象类

9、抽象方法要被实现,所以不能是静态的,也不能是私有的。

10、接口可继承接口,并可多继承接口,但类只能单根继承。

最后看看代码实现(☄⊙ω⊙)☄

using System;

namespace Test_10_ChouXiangLei
{
    // 此例抽象类的代码
    // 抽象方法只能出现在抽象类中
    // 抽象类不能直接实例化
    // 抽象方法是只有定义、没有实际方法体的函数,它只能在抽象函数中出现,
    // 并且在子类中必须重写;虚方法则有自己的函数体,已经提供了函数实现,但是允许在子类中重写或覆盖。
    public abstract class Food
    {

        // 抽象方法 需要添加abstract关键字
        // 1.在父类中定义的抽象方法不能够实现
        public abstract void Eat ();

        // 抽象类中可以包含普通的方法
        public void Test ()
        {
            Console.WriteLine ("普通方法");
        }
    }

    public class Apple:Food
    {
        // 2.子类实现父类的抽象方法时,需要添加override关键字
        public override void Eat ()
        {
            Console.WriteLine ("HP + 10");
        }
    }

    public class Water:Food
    {

        public override void Eat ()
        {
            Console.WriteLine ("MP + 10");
        }
    }

    class MainClass
    {
        public static void Main (string[] args)
        {
            Food f1 = new Apple ();
            Food f2 = new Water ();

            f1.Eat ();
            f2.Eat ();
            f1.Test ();
        }
    }
}
using System;

namespace Test_14_JieKou
{
    // 此例是接口的代码
    // 接口用来解耦和,回调,在项目开发初,抽象类用来定原型,接口用来确定功能
    public class A
    {

    }

    // 食物接口
    public interface Food
    {
        // 在接口中定义属性,属性也不能实现
        float Price{ get; }

        // 在接口中定义方法
        // 1.不能添加访问修饰符,默认都是public
        // 2.在接口中的方法不能实现
        void Eat ();
    }

    // 苹果类
    // Apple 继承于A类 并且实现了Food接口
    // 3.一旦某个类实现了接口就必须实现接口中定义的全部成员
    public class Apple:A,Food
    {
        public float Price {
            get {
                return 1.4f;
            }
        }

        // 实现了Food接口中的Eat方法
        public void Eat ()
        {
            Console.WriteLine ("吃下苹果后HP + 10");
        }
    }

    public class Banana:Food
    {

        public void Eat ()
        {
            Console.WriteLine ("吃下香蕉后,HP - 10");
        }

        public float Price {
            get {
                return 5.6f;
            }
        }


    }

    class MainClass
    {
        public static void Main (string[] args)
        {
            Apple a = new Apple ();
            //a.Eat ();
            //Console.WriteLine (a.Price);

            // 多态 - 使用接口实现的多态
            Food b = new Apple ();
            //b.Eat ();
            //Console.WriteLine (b.Price);

            Banana banana = new Banana ();
            banana.Eat ();
            // 4.不能够直接实例化接口
//          Food f = new Food ();
        }
    }
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值