代码之家  ›  专栏  ›  技术社区  ›  Techmaddy

为什么接口比抽象类更受欢迎?

  •  38
  • Techmaddy  · 技术社区  · 17 年前

    • 实现不是硬编码的

    23 回复  |  直到 17 年前
        1
  •  55
  •   DevinB    17 年前

    1. 恕我不同意。

    多接口继承,继承迫使类做出实现选择,接口可以更容易地更改。

    首先,强调界面的积极方面,这是必须的。

        2
  •  26
  •   TofuBeer    17 年前

    interface
       abstract class
           concrete class 1       
           concrete class 2
    

    • 已经扩展了某些内容的现有类可以实现该接口(假设您可以控制现有类的代码)

    您应该始终(除非您有充分的理由不这样做)将变量(实例、类、局部和方法参数)声明为接口。

        3
  •  23
  •   Joel Coehoorn    17 年前

    你只有一次继承权。如果你创建了一个抽象类而不是一个接口,那么继承你的类的人就不能同时继承不同的抽象类。

        4
  •  10
  •   Rowland Shaw    17 年前

        5
  •  9
  •   Warrior    17 年前

    抽象类

    1.不能独立于其派生类进行实例化。抽象类构造函数仅由其派生类调用。

    2.定义基类必须实现的抽象成员签名。

    3.比接口更具可扩展性,不会破坏任何版本兼容性。使用抽象类,可以添加所有派生类都可以继承的其他非抽象成员。

    1.无法实例化。

    3.用额外的成员扩展接口会破坏版本兼容性。

    4.无法存储任何数据。只能在派生类上指定字段。解决方法是定义属性,但不实现。

    6.虽然不能出现默认实现,但实现接口的类可以继续相互派生。

        6
  •  7
  •   Community Mohan Dere    9 年前

    devinb

    “你只能继承一次” .

        7
  •  5
  •   Eddie    17 年前

    super() equals()

    当你想共享一个实现时,使用接口可以鼓励使用组合。组合通常是重用其他对象的更好方法,因为它不那么脆弱。继承很容易被过度使用或用于错误的目的。

    定义一个接口是一种非常安全的方式来定义一个对象应该如何运作,而不会有脆弱的风险

    此外,正如您所提到的,一次只能扩展一个类,但您可以实现任意数量的接口。

        8
  •  4
  •   paulmurray    17 年前

    JDBC标准规定“连接必须

        9
  •  3
  •   krosenvold    17 年前

    当你使用抽象类时,你在子类和基类之间创建了一个耦合。这种耦合有时会使代码很难更改,特别是当子类数量增加时。接口没有这个问题。

        10
  •  3
  •   Neal Stublen    17 年前

    “为什么接口比

    与大多数编程构造一样,它们是有原因的,像面试问题中这样的绝对陈述往往会忽略这一点。这让我想起了你以前读过的关于 转到 转到 转到

        11
  •  3
  •   Pat    17 年前


    了解你的答案背后的哲学,否则你就完了(至少如果我采访你的话)


    任何事物

    public void foo(Hashtable bar);
    

    vs。

    public void foo(Map bar);
    


    第三,接口允许具体类实现中的公共方法是“私有的”。如果该方法未在接口中声明,则没有业务使用该方法的类不能使用(或误用)该方法。这就引出了第四点。。。。


    public interface FragmentVisitor {
        public void visit(Node node);
    }
    


    当然,一些这样的方法可以被保护。然而,遗憾的是,同一包中的其他类也可以看到受保护的方法。如果抽象类的方法实现了接口,那么该方法必须是公共的。

    然而,使用接口时,在查看抽象超类或具体类时,所有这些内部结构都被安全地隐藏起来。


        12
  •  2
  •   scott    15 年前

    如果他们认为X比Y好,我就不会担心得到这份工作,我也不喜欢为那些强迫我做一种设计而不是另一种设计的人工作,因为他们被告知界面是最好的。两者都是好的,具体取决于情况,否则为什么语言选择添加抽象类?当然,语言设计师比我聪明。

        13
  •  2
  •   Marco167    13 年前

    这就是“多重继承”的问题。 我们一次只能通过另一个类“扩展”不超过一个abstract类,但在Interfaces中,我们可以在单个类中“实现”多个接口。 因此,虽然Java一般不提供多重继承,但通过使用接口,我们可以在其中包含multiplt继承属性。

        14
  •  1
  •   Tom Hawtin - tackline    17 年前

    interface s是编写纯抽象类的一种更简洁的方法。您可以看出实现并没有悄悄进入(当然,您可能希望在某些维护阶段这样做,这会使接口变得糟糕)。就是这样。客户端代码几乎没有明显的区别。

    接口的缺点是,编译器无法识别一些不可能的转换/ instanceof

        15
  •  1
  •   Thorbjørn Ravn Andersen    17 年前

    上面没有提到一个原因。

    看 http://tutorials.jenkov.com/java-reflection/dynamic-proxies.html 作为教程。

        16
  •  0
  •   user68610    17 年前

        17
  •  0
  •   Marko    17 年前

        18
  •  0
  •   Chochos    17 年前

    这就是为什么JDBC是所有接口;你并不真正关心JDBC实现中使用了什么类,你只需要任何JDBC实现都具有相同的预期行为。在内部,Oracle JDBC驱动程序可能与PostgreSQL驱动程序非常不同,但这与您无关。一个可能必须继承数据库开发人员已经拥有的一些内部类,而另一个可能完全从头开始开发,但这对你来说并不重要,只要它们都实现了相同的接口,这样你就可以在不知道任何一个内部工作原理的情况下与其中一个进行通信。

        19
  •  0
  •   Yorch    17 年前

    好吧,我建议这个问题本身应该重新表述。接口主要是类获取的契约,契约本身的实现会有所不同。抽象类通常包含一些默认逻辑,其子类将添加更多逻辑。 我想说,这些问题的答案取决于钻石问题。Java防止多重继承以避免这种情况( http://en.wikipedia.org/wiki/Diamond_problem

        20
  •  0
  •   Manoj    17 年前

    接口?".

    我对这个具体问题的回答是:

    这意味着无论JDBC供应商提供或使用何种实现层次结构,JDBC api的接口层次结构都可以不断发展。

        21
  •  0
  •   gregturn    17 年前

    SwingWorker 。它定义了一个在后台做某事的框架,要求用户定义 doInBackground() 对于实际任务。

    我扩展了这个类,使其自动创建了一个弹出进度条。我重写了done(),以控制此弹出窗口的处理,但随后提供了一个新的重写点,允许用户可选地定义进度条消失后会发生什么。

    public abstract class ProgressiveSwingWorker<T, V> extends SwingWorker<T, V> {
    
        private JFrame progress;
    
        public ProgressiveSwingWorker(final String title, final String label) {
            SwingUtilities.invokeLater(new Runnable() {
                @SuppressWarnings("serial")
                @Override
                public void run() {
                    progress = new JFrame() {{
                        setLayout(new MigLayout("","[grow]"));
                        setTitle(title);
                        add(new JLabel(label));
                        JProgressBar bar = new JProgressBar();
                        bar.setIndeterminate(true);
                        add(bar);
                        pack();
                        setLocationRelativeTo(null);
                        setVisible(true);
                    }};
                }
            });
        }
    
        /**
         * This method has been marked final to secure disposing of the progress dialog. Any behavior
         * intended for this should be put in afterProgressBarDisposed.
         */
        @Override
        protected final void done() {
            progress.dispose();
            try {
                afterProgressBarDisposed(get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    
        protected void afterProgressBarDisposed(T results) {
        }
    
    }
    

    doInBackground()

    new ProgressiveSwingWorker<DataResultType, Object>("Editing some data", "Editing " + data.getSource()) {
    
        @Override
        protected DataResultType doInBackground() throws Exception {
            return retrieve(data.getSource());
        }
    
        @Override
        protected void afterProgressBarDisposed(DataResultType results) {
            new DataEditor(results);
        }
    
    }.execute();
    

    这展示了抽象类如何很好地提供模板化操作,与定义API契约的接口概念正交。

        22
  •  0
  •   Pankaj    16 年前

    关于这个问题,你有很多答案。

        23
  •  0
  •   Community Mohan Dere    9 年前

    .

    接口: 通过多个不相关的对象实现合约

    抽象类:


    关于接口和抽象类的用例,请参考这个相关的SE问题

    Interface vs Abstract Class (general OO)

    Template_method 模式,你无法用界面来实现。

    如果你必须为许多未标记的对象实现一个功能,抽象类就达不到目的,你必须选择 .