• 辣么大
    2019-11-20
    如果让我聊聊接口和抽象类,我会这么聊:定义、区别(是什么),存在意义(从哪来),应用(到哪去)。
    1、定义:
    抽象类:不允许实例化,只能被继承;可包含属性和方法,包含抽象方法;子类继承抽象类必须重写抽象方法。
    接口:不允许实例化,只能被实现;不包含属性和普通方法,包含抽象方法、静态方法、default 方法;类实现接口时,必须实现抽象方法。
    2、意义:
    抽象类:解决复用问题,适用于is-a的关系。
    接口:解决抽象问题,适用于has-a的关系。
    3、应用:
    例如:
    解决复用问题:java中的子类FileInputStream和PipeInputStream等继承抽象类InputStream。重写了read(source)方法,InputStream 中还包含其他方法,FileInputStream继承抽象类复用了父类的其他方法。
    解决抽象问题:抽象类InputStream实现了Closeable接口,该接口中包含close()抽象方法。Closeable这个接口还在很多其他类中实现了,例如Channel,Socket中都有close() 关闭这个功能,但具体实现每个类又各有不同的实现,这个就是抽象。

    4、补充知识点(语法):
    Java接口中可以定义静态方法、default方法,枚举类型,接口中还可以定义接口(嵌套)。
    public interface ILog {
      enum Type {
        LOW,
        MEDIUM,
        HIGH
      }
      interface InILog{
        void initInLog();
      }
      default void init() {
        Type t = Type.LOW;
        System.out.println(t.ordinal());
      }
      static void OS() {
    System.out.println(System.getProperty("os.name", "linux"));
      }
      void log(OutputStream out);
    }
    class ConsoleLog implements ILog {
      @Override
      public void log(OutputStream out) {
        System.out.println("ConsoleLog...");
      }
    }
    展开
     12
     132
  • NoAsk
    2019-11-20
    Java使用abstract表示抽象类,interface表示接口。
    老师讲的很好,我补充一下使用;
    1.java中抽象类是类,而java不支持多继承,当想要实现多继承的时候只能使用表示has-a的接口来实现。
    2.在java8之前,定义的接口不能有具体实现,这会导致在后续维护的时候如果想要在接口中新增一个方法,必须在所有实现类中都实现一遍,并且只有几个新的实现类可能要去具体实现,其他的都只是加上默认实现,这样比较麻烦。在java8中接口可以用使用关键字default,来实现一个默认方法,这样就解决了上述的麻烦。
     1
     51
  • Maurice
    2019-11-21
    嗯,刚刚看了一下评论区,小弟给大家初学设计模式以及刚刚接触项目的同学一些建议,其实在学这一章更以及往后正式的20多种设计模式时候更加锻炼的是一种抽象思维,以我个人的一点经验,就像老师一开始说的,在学习的时候,不要总是类比生活中的一些阿猫啊狗的例子,没错初次是很好理解,而且你会感觉好像懂了,但是实际上你还是不懂(可能是以为我笨),建议大家没学习一种模式的时候,思考一下现在在做的项目中那些业务可以进行优化,如果可以的话,可以进行重构,这样对你的学习才有很大的帮助;举个栗子,例如策略模式,我们在代码是不是经常调用第三方接口,每个接口都有它的规范之类的,如果你按照low 的方式就是按照规范组织一些报文请求,但是这个时候,你可以用的你的抽象思维,比如,在这类业务中,无外乎就是,1、构建报文,2、请求结构,3、解析返回,那么我就可以这样设计:
        /**
         * 请求统一接口
         */
        public interface Fun<T> {
            /**
             * 发送请求报文
             */
            String constructionRequest();
            /**
             * 请求报文
             */
            String doPost(String request);
            /**
             * 解析回执报文
             */
            T resolveResponse(String responseText);
        }
    然后再写一个策略的算法簇(应该是这么叫)
    /**
     * 统一实现接口
     */
    public class DealWithHandle {
        
        /**
         * 描述 create.
         *
         * @param <T> the type parameter
         * @param fun the fun
         * @return the t
         * @author Maurice Mao
         * @created 2018 -07-13 10:58:32 Handle t.
         */
        public static <T> T handle(Fun<T> fun) {
            
            String request = fun.constructionRequest();
            
            String response = fun.doPost(request);
            
            T t = fun.resolveResponse(response);
            
            return t;

        }
    }
    这个时候,假设你做支付宝扫码支付的时候(或者微信以及第三方支付),是不是可以这么调用:
    public class OfficialAliScan {

        private static Logger logger = LoggerFactory.getLogger(OfficialAliScan.class);

        public static ApiTradeResultDto operate(final TradeOrderDO orderDO, final SubMerchatAuthDO subMerchatAuthDO, final String authCode) {
            return DealwithHandle.handle(new DealwithHandle.Fun<ApiTradeResultDto>() {
                @Override
                public String constructionRequest() {
                      ///todo
                }

                @Override
                public String doPost(String bizContent) {
                    ///todo
                }

                @Override
                public ApiTradeResultDto resolveResponse(String responseTxt) {
                    ///todo
                }
            });
        }
    这样的话,你的业务代码组织的就很清晰,也便于调试维护
    展开
     3
     27
  • 侯金彪
    2019-11-20
    接口强调具有什么能力(has-a),
    抽象类强调是什么(is-a)。
    
     20
  • Daiver
    2019-11-20
    go和java 都有接口设计,但go的设计是飞入侵入性(duck type),而java必须显式实现该借口,这一点go做的真的好了。
     9
     14
  • helloworld
    2019-11-21
    『那又如何避免这个类被实例化呢?实际上很简单,我们只需要将这个类的构造函数声明为 protected 访问权限就可以了。』当把一个类的构造方法声明为protected后,在同一个包的其他类中还是可以new这个类的对象的。老师,是我想错了吗?请老师指正

    作者回复: 好像我写的是有点问题,稍后更正下,多谢指出

     4
     8
  • 熊斌
    2019-11-20
    举个例子吧,附件上传服务端实现

    需求:支持上传、下载、删除以及文件的存储,存储的话需要支持存本地和云端,涉及附件上传的业务点有十几个。

    设计思路:
    1、接口设计:上传、下载、删除是公共行为,抽象到接口中

    2、存储方法是一大块公共代码,写到抽象类里面

    3、每个业务的附件上传子类实现接口、继承抽象类
    展开
     3
     8
  • 五岳寻仙
    2019-11-21

    Python中抽象类是通过 abc 模块中的 abstractmethod 和 ABCMeta

    from abc import abstractmethod, ABCMeta

    class BaseClass(metaclass=ABCMeta):
        @abstractmethod
        def fun(self, x): pass

    因为 Python 需要天然支持多继承,所以可以直接用上述的抽象类实现接口
    展开
    
     7
  • 梦倚栏杆
    2019-11-20
    关于抽象类和接口有一个疑问,也可能是对业务模型不够了解,同一件事其实可以表达成is a也可以表达成has a,这个就看你的语言描述到底是个名词还是行为。
    举例说明:
    宠物猫和宠物狗都是宠物。
    宠物猫和宠物狗都有会被宠。
    is a基类定义:宠物类
    has a 接口定义:可被宠的
    如果取决于需求的语言阐述,感觉就太依赖个人表达习惯了,这不是一个团队持续迭代好项目的方式吧
    希望老师可以帮忙解惑
    展开
     2
     7
  • 大牛凯
    2019-11-20
    Python有抽象类吧?abc不是可以定义抽象类么
     2
     6
  • 👽
    2019-11-25
    个人认为,jdk8中,接口的默认实现之后。接口和抽象的区别渐渐模糊了。接口,从一定程度上也可以当抽象类使用。而且最主要的是,支持多实现,但不支持多继承。
    并且,我认为,多实现也是接口和抽象类最主要的区别,没有之一!

    我的理解:
    抽象类:描述整个类的一个概况。(举例来说,抽象类,爬行动物)
    接口: 描述的是需要具备的能力。(举例来说,飞行,游泳)

    乌龟,在类上,应该继承爬行动物。因为属于爬行动物(说实话不确定是不是爬行动物),但是乌龟同时也会游泳。会游泳,就只能是乌龟实现的接口。如果,有一天,乌龟长翅膀会飞了(致敬超级马里奥),那这时候,实现会飞行接口就可以了。

    在使用到这个接口的角度,某个游戏,需要十个飞行的小怪。以前是十个各种鸟类。但是现在需要十一个了,于是乎给乌龟安上了翅膀(实现飞行接口),拿来充当飞行小怪使用。
    展开
    
     5
  • Smallfly
    2019-11-20
    抽象类 vs 接口

                抽象类 接口
    实例化         否     否
    属性         是 否
    方法 是 是
    实现 是 否
    目的 复用 扩展
    意义 is-a has-a
    展开
     1
     4
  • Uncle.席
    2019-11-20
    接口强调某一方面的统一,抽象强调共性的复用
    
     4
  • bigtom
    2019-11-23
    is-a 和 has-a 的地方我觉得有点问题。应该说 is-a 是继承(Inheritance),has-a 是组合(Composition)。所以我感觉无论接口还是抽象类都是继承,所以都是 is-a 的关系呀。
    
     3
  • 张飞online
    2019-11-20
    谈谈c吧,linux内核的设备驱动总线模型,就但说设备吧,

    抽象类:
    首先来个通用设备结构体,到了具体设备把通用设备结构体包含了,这是典型的抽象类思想,提炼公共部分做基类,提高复用度。
    接口,接口实现就是函数指针,不管你的驱动如何实现,接口不变,你就按照函数指针的定义实现函数,任何人都要受控这个函数定义协议。
    
     3
  • nelson
    2019-11-20
    抽象类 Strategy 没有定义任何属性,并且所有的方法都声明为 virtual 类型(等同于 Java 中的 abstract 关键字)
    这里关于C++的说明有点问题,virtual是虚函数和abstract没有对应关系,换句话说,java中成员函数都是virtual的。Java中的abstract关键字对应“virtual void algorithm()=0”当中的“=0”,也就是所谓的纯虚函数,即在本类中没有实现,派生类必须实现
    
     3
  • Dimple
    2019-11-20
    1. 目前学习的就是Java余元,所以有了一套线程的支持接口和抽象类的东西。其实刚入门的时候,确实对这两个不是很理解,而且很多时候都不知道如何运用,那时候是靠《疯狂Java讲义》学会了区别,并且通过一些面试题了解到其中的一些区别和使用方式。
    2. 通过今天老师的讲解,我又结合了《疯狂Java讲义》、面试题、以及自己项目中的代码实现,来重新梳理这两个的区别。为什么我的业务代码是使用接口而不是抽象类,为什么有些API是用了抽象类而不是接口,是基于某方面的考虑,是处于什么方式的考虑,或是基于哪个设计模式。不过这些都还需要消化,沉淀,会用只是一方面,会思考,会架构才是更好的方式。
    
     3
  • 编程界的小学生
    2019-11-20
    1.普通类模拟抽象类方法:
    私有构造器,protected修饰的方法和成员变量,模拟抽象方法的时候在实现体内直接抛出异常并写好交由子类具体实现的注释说明
    2.用的JAVA。天然支持,abstract和interface
    3.抽象类:
    不支持多继承,为了解决代码复用问题而产生,他可以内部定义方法实现、公用属性以及需要子类各自实现的抽象方法,应用场景最典型的就是模板模式,is a的关系。爸爸儿子的关系。
    接口:
    支持多继承,为了让代码更加解耦合,更加灵活而产生,他所定义的方法都是抽象的,has a的关系,好比一种协议,一种规范,应用场景贼广泛,比如各大设计模式,设计原则。再比如责任链模式
    展开
     3
     3
  • 默
    2019-11-20
    Java语言接口和抽象的用法老师已经在文中讲了,但在后来的语法规则里,接口也可以由default修饰符来构造默认的接口方法逻辑了,这样在实现接口的时候可以不用必须实现包含被标记为default的方法了,这样的设计是否也是因为接口中如果包含了通用的方法逻辑,可以不用每个接口都实现一遍,避免方法逻辑冗余呢?也是复用的一种思想?
    
     3
  • 香蕉派2号
    2019-11-20
    问题1:
    c#接口两种实现方式:
    // 直接实现接口
    interface IAttack
    {
        void Attck();
    }
    class Gun : IAttack
    {
        public void Attck()
        {
            throw new NotImplementedException();
        }
    }
    class Rifle : IAttack
    {
        public void Attck()
        {
            throw new NotImplementedException();
        }
    }

    // 显示实现接口(当多个接口的中需要实现的方法名称一样的时候)
    interface IAttack
    {
        void Attack();
    }
    interface ISpecialAttack
    {
        void Attack();
    }
    class Gun : IAttack, ISpecialAttack
    {
        public void Attack()
        {
            Console.WriteLine("普通攻击");
            throw new NotImplementedException();
        }
        void ISpecialAttack.Attack() // 接口的显示实现
        {
            Console.WriteLine("特殊攻击");
            throw new NotImplementedException();
        }
    }
    class Rifle : IAttack, ISpecialAttack
    {
        public void Attack()
        {
            Console.WriteLine("普通攻击");
            throw new NotImplementedException();
        }
        void ISpecialAttack.Attack() // 接口的显示实现
        {
            Console.WriteLine("特殊攻击");
            throw new NotImplementedException();
        }
    }
    public class TestWeapons
    {
        public void TestMethod()
        {
            ISpecialAttack desertEagle = new Gun();
            desertEagle.Attack();

            IAttack rifle = new Rifle();
            rifle.Attack();
        }
    }


    c#抽象类定义以及实现:
    abstract class Weapon{
        public float attackRange;
        public float damage;
        public virtual void Attack(Enemy enmey)
        {
            enmey.health -= damage;
            Console.WriteLine("attack...");
        }
    }

    class Gun: Weapon
    {
        public override void Attack(Enemy enmey)
        {
            base.Attack(enmey);
        }
    }

    public class TestWeapon02
    {
        public static void main02(string[] args)
        {
            Enemy enemy = new Enemy();
            Weapon gun = new Gun()
            {
                damage = 5,
                attackRange = 100,
            };
            gun.Attack(enemy);
            Console.WriteLine("enemy health: " + enemy.health);
        }
    }

    问题2:
    总的来说,抽象类就是类别上的总称;接口就是行为上的规范

    展开
     1
     3
我们在线,来聊聊吧