• C#知识点:抽象类和接口浅谈


    首先介绍什么是抽象类?

    抽象类用关键字abstract修饰的类就是叫抽象类,抽象类天生的作用就是被继承的,所以不能实例化,只能被继承。而且 abstract 关键字不能和sealed一起使用,因为sealed是不允许继承,这样就是抽象类的意义冲突了。

        public abstract class Test
        {
    
    
        }

      现在我们知道知道了抽象类长的什么样了,下面要知道抽象类是干嘛用的。顾名思义把对象共有的东西抽象出来。比如猫和和狗鸟等都有眼睛,都有嘴巴。那我们就可以抽象出一个动物类。把眼睛和嘴巴放到这这些公共的部分抽象到动物类里里面。用来对继承于动物类的子类进行约束。下次在有一个狗。只要继承于动物类那么狗必须实现眼睛和嘴巴。

     Dog类 继承了 Animal抽象了。VS提示我们没有实现抽象类Animal类的两个方法。由此可以看出抽象类是对子类的约束。说白了。抽象类就是对子类的抽象,即将子类中的公共部分提取出来,放到一个特定的类中。抽象类是一份合约,用于为同一类型(这里类型不是指数据类型,而是逻辑上的划分,如人和猫都是动物)的子类提供约束。约束他们的公共部分。

     现在来总结下抽象类。

    1.抽象类的定义需要abstract关键字

    2.抽象类的存在的意义就是被继承的。所以不能实例化,不能与sealed关键字一起用。

    3.抽象类允许存在非抽象方法和抽象方法。

    4.抽象类的抽象成员,子类必须实现。

    在来看看接口,接口和抽象类很多概念相似。接口的创建要用到interface,接口出现的意义也是被继承。也不能与sealed关键字一起用

        public interface Animal
        {
            void Run();
            void Say();
        }

    接口的和抽象类功能一样,也是抽象公共部分。

     从逻辑上与抽象类区分的话。总结成一句话。就是接口约束子类对象的行为。抽象类是将同一类型类的公共部分提取出来,进行约束。注意这里的同一类型不是数据类型而是逻辑上的,比如人和啊猫啊狗都是动物。

    来总结下两者的区别

    1.学过C#的都知道类只能单继承,接口可以多继承。这个就是抽象类和接口的第一个区别。

    2.接口不能包含已经实现成员,但是抽象类是可以的

    3.接口的成员默认1实现是public的,但是抽象类的成员可以被访问修饰修饰但是不能是私有的。

    4.抽象类多用于约束对象的核心基础成员,接口对于用于约束子类的行为。比如类型有哪些行为(方法)。

    5.接口成员如果变动的话,实现子类全部都要变动,抽象只有抽象成员变动了子类才要变动。

    6.接口不允许定义字段,抽象允许定义字段,但是不允许定义抽象字段。

     

    最有精华的两句话

    • 抽象类和接口都是一种约束,这种约束使我们的代码有更好的层次结构,特别是在多人协同开发时(若每个人都按照自己的习惯来,对整个开发团队而言,开发成本不知要提高多少)。

    • 抽象类是对相同类型(不是数据类型)子类公共部分的抽象(约束),接口是对能力的一种约束

    抽象类 VS 接口

     

    引言

    接口和抽象类是面向对象编程(OOP, Object Oriented programming)中两个绕不开的概念,二者相似而又有所不同。接下来,我们来了解二者的概念并比较它们的异同。

    什么是抽象类型?

    抽象类是一种特殊的类,该类不能被实例化。抽象类的存在就是为了被继承,即抽象类可以被其它类继承但不能被实例化。那么,我们为什么需要一个无法被实例化的类呢?这样做的优点是,通过抽象类我们制定了一份强制所有子类必须遵守的合约,使所有子类有着一致的层次结构。抽象类提供了一种规范用于规定子类如何进行工作,子类可根据自身情况来重写抽象类中的抽象成员(及其它可被重写的成员)以满足自身需求。

    抽象类作为一个基类,可以包含已实现的成员,同时应至少包含一个抽象成员,否则就没必要使用抽象类了。如果一个抽象类中仅仅包含抽象方法,那么这时抽象类就和接口很像了。

    什么是接口?

    接口中不能包含任何被实现的成员,即接口中只能包含成员的签名。如,没有方法体的方法、只包含访问器关键字(set、get)的属性等。和抽象类类似,接口也是一份合约。C#中,接口和抽象类的主要区别是,类可以实现多个接口,但只能继承一个(抽象)类。

    比较异同

    特征接口抽象类
    是否支持多继承 支持 不支持
    默认实现 接口中不能包含任何已实现的成员 抽象类中可以包含已实现(非抽象)的成员
    访问修饰符 接口成员默认是公共(public)的,不再允许被任何访问修饰符修饰 抽象类成员可以被访问修饰符(不能是private)修饰
    核心 VS 辅助 接口多用于定义(辅助性的)能力 抽象类多用于定义相同类型(这里类型不是数据类型的意思,解释见下文)子类所共有的一些特征
      若只提供一些方法上的约束,建议使用接口 如果子类属于同一类型,且具有相同的行为或状态,建议使用抽象类提供约束
    寻找成员速度 相比抽象类较慢 相比接口更快
    成员变动的影响 如果接口成员发生改动,则所有实现类都要进行改动 若向抽象类中添加非抽象成员,我们可以给该成员提供默认实现,这样子类就无需发生变动
    允许包含的抽象成员 属性、方法、事件、索引器(这四类本质上都是方法) 属性、方法、事件、索引器
    是否允许定义字段 不允许 不允许定义使用abstract修饰的字段

    抽象类是对子类的抽象,即将子类中的公共部分提取出来,放到一个特定的类中。抽象类是一份合约,用于为同一类型(这里类型不是指数据类型,而是逻辑上的划分,如人和猫都是动物)的子类提供约束。
    接口也是一份合约,但接口多用对能力的定义,即用于指定实现类能做哪些事儿。

    人和猫,都属于动物这个大类,我们可以抽象出二者的公共部分。如,年龄、体重、吃、会叫(用于形容人不太友好)等作为一个抽象类的成员。

    复制代码
    abstract class Animal
    {
        public abstract int Age { set; get; }
        public abstract float Weight { set; get; }
        public abstract void Call();
        //默认实现
        public virtual void Eat()
        {
            Console.WriteLine("猫粮......");
        }
    }
    
    
    class Person : Animal
    {
        public override int Age { set; get; }
        public override float Weight { set; get; }
    
        public override void Eat()
        {
            Console.WriteLine("鱼香肉丝盖饭......");
        }
    
        public override void Call()
        {
            Console.WriteLine("雷好啊......");
        }
    }
    
    class Cat : Animal
    {
        public override int Age { set; get; }
        public override float Weight { set; get; }
    
        public override void Call()
        {
            Console.WriteLine("喵喵喵......");
        }
    }
    复制代码

    那么,只要继承Animal类的类都应属于动物这个大类,汽车就不应该继承Animal类。
    此外,人和猫相比,人会制作工具而猫不行,那么制作工具的技能就是人所特有的,这时可以定义一个接口提供对制作工具这项技能的约束,然后让Person类实现该接口。

    复制代码
    interface ICreatTool
    {
        void CreateTool();
    }
    
    class Person : Animal, ICreatTool
    {
        public override int Age { set; get; }
        public override float Weight { set; get; }
    
        public override void Eat()
        {
            Console.WriteLine("鱼香肉丝盖饭......");
        }
    
        public override void Call()
        {
            Console.WriteLine("雷好啊......");
        }
    
        public void CreateTool()
        {
            Console.WriteLine("造台MAC......");
        }
    }
    复制代码

    再如,人、车、猫三者都可以跑,那么也可以定义个接口用于对跑这项技能提供约束。

    复制代码
    interface IRun
    {
        void Run();
    }
    
    class Person : IRun
    {
        public void Run()
        {
            Console.WriteLine("11路公交......");
        }
    }
    
    class Cat : IRun
    {
        public void Run()
        {
            Console.WriteLine("四蹄奔腾......");
        }
    }
    
    class Car : IRun
    {
        public void Run()
        {
            Console.WriteLine("四轮......");
        }
    }
    复制代码

    小结

    用简单的话概括接口和抽象类的异同:

    • 抽象类和接口都是一种约束,这种约束使我们的代码有更好的层次结构,特别是在多人协同开发时(若每个人都按照自己的习惯来,对整个开发团队而言,开发成本不知要提高多少)。

    • 抽象类是对相同类型(不是数据类型)子类公共部分的抽象(约束),接口是对能力的一种约束。

  • 相关阅读:
    Spring5.2.x04BeanDefinitionMap
    spring配置类解析
    spring5 解析配置类
    分布式唯一id生成器
    电脑变流畅的方法(也是网吧电脑比家里的电脑流畅的原因)
    nginx启动访问
    Win10按f5不能刷新页面 变成了调节亮度怎么办?
    Linux 内核定时器
    Linux 中断下半部工作队列(work queue)
    Linux 虚拟字符设备globalmem
  • 原文地址:https://www.cnblogs.com/ztf20/p/9118055.html
Copyright © 2020-2023  润新知