【问题标题】:OOP the point of interface [duplicate]OOP接口点[重复]
【发布时间】:2011-08-24 22:19:02
【问题描述】:

可能重复:
Interface vs Abstract Class (general OO)

编辑: 我刚刚阅读了“可能重复”中问题的问题和答案,我感到非常难过有人认为这两个问题甚至相似......但是,哦,好吧......

------------------------------------------ -----------------------------

大家好, 我正在尝试了解有关 OOP 范式中的接口的一些信息。 我知道抽象类和接口之间的区别,我也知道接口基本上允许简单的多重继承行为和设计,但我没有得到的是“承诺原则”。我的意思是,接口应该是一个实现接口的类实现所有接口方法的承诺。

我不明白的是,每次调用它的方法时,我们是否必须检查类是否实现了带有 instanceOf 的接口?如果不阅读文档,您将不知道某些类实现了接口。如果您阅读代码,您会发现自己定义了该方法并且您可以调用它?!

如果我有

案例A。

class Ball{
function kick(){...};
}

或 案例B。

interface Kickable{
function kick;
}

class Ball implements Kickable{
function kick(){...};
}

唯一的区别是,如果 A 在调用不存在的方法(“运行时”)时我会收到错误,而如果 B 在尝试运行代码时会收到此错误,而试图“编译”。这里runtime和compile肯定用错了(PHP环境)。

我记得在 Java 中有一个 Runnable 接口可以启用线程。为什么我们必须实现一个接口 Runnable 然后在那个类中定义 run() 方法?我的意思是,类可以有一个 Run 方法而不实现接口,并且有办法检查类是否定义了特殊方法。好的,也许我的 Java 部分问题有点令人困惑:)))

对于这样一个令人困惑的问题,我很抱歉,但我希望有人在理解这些问题时能够理解,现在他可以分享他的结论:)

谢谢, 卢卡

【问题讨论】:

  • 一旦有了接口变量,就不必检查任何东西,只需按原样调用方法即可。要知道哪些方法可用,您确实需要阅读文档或代码(或使用代码洞察力)。
  • fwiw:接口通过让我能够轻松注入(用于该测试)不需要的类的其他实现,极大地帮助我测试我的代码。
  • instanceOf 正是您不应该在纯 OOP 中使用的内容。看看 Liskov 替换原则 (LSP)。
  • 想要编译时检查,即强制传递给方法的参数类型。这就是 Java 擅长而 PHP 不擅长的地方。 Java 不允许您编译,因此运行损坏的代码(例如,在接口没有的接口上调用方法),但 PHP 不会为您检查任何内容 - 您可以调用未定义的方法,如果传递的对象有它们(或使用 __call 方法),它会工作。
  • @Ondrej:我不确定我是否做对了,但是 PHP 不允许运行脚本,其中类缺少在同一个类实现的接口中定义的方法的实现...当然 PHP 将允许很多 Java 和 C# 不允许的东西......不幸(或幸运)

标签: php oop interface multiple-inheritance


【解决方案1】:

没有。您不必使用 instanceof。那是用于运行时类型检查。 如果您想确保您使用的是实现该接口的类,只需将接口类型放在您的方法签名中。例如

public interface yourInterface{
      public void foo();
}

public class yourClass implements yourInterface{
     public void foo(){} //you need to implement this method, otherwise it won't compile
}

public class anotherClass{
     public void bar(yourInterface object){} //you can pass any object to "bar" method if the object implements yourInterface. yourClass object will be fine
}

然后你可以做一些其他的好事,取决于你的语言。例如,使用 java,您可以强制泛型类型实现给定接口,从而允许泛型编程:

class generiClass<T extends yourInterface>{
      public void genericMethod(T object){} //you can use a generic T class, but T needs to implement yourInterface
}

接口的原因主要有2个:

  1. 强制类实现某些方法
  2. 在没有多重继承的语言中允许类似特性的多重继承(在像 C++ 这样具有多重继承的语言中,您不需要接口。或者更好地说,接口与纯抽象类完全一样)

【讨论】:

    【解决方案2】:

    您已经在问题中提到了接口的大部分好处,即:

    • 它们允许多重(接口)继承

    您还提到您知道抽象类和接口之间的区别。这就是使用接口的另一个好处:

    • 任何类都可以实现接口,但不是任何类都可以派生自抽象类

    这基本上是对上述第一点的重新散列,但它提出了您以前可能没有考虑过的观点。以您的 Java Runnable 为例:如果 Runnable 是一个抽象类,那么 任何实现线程的 类都需要从它继承。这最终会导致代码极其不灵活,因为您无法从任何其他基类继承。但是,由于 Runnable 是一个接口,因此您可以让任何类实现它(无论它可能继承自哪个基类)。

    我理解您对必须检查类是否实现接口的担忧 - 不幸的是,在弱类型语言中您将不得不这样做,特别是因为 PHP 类型提示尚未完全发挥作用。

    在像 Java 这样的强类型语言中,您通常不会有这样的顾虑,因为如果您在未实现接口(或未实现)的类上调用接口方法,则会收到编译时错误t实现具体方法)。

    【讨论】:

      【解决方案3】:

      “我也知道接口基本上允许简单的多重继承行为和设计”

      我认为你误解了那部分。接口允许您确保特定类具有一组属性/方法。

      例子:

      function foo($obj) {
        $obj->bar(); // fails with foo(array());
      }
      

      对比:

      interface foobar {
        function bar();
      }
      
      function foo(foobar $obj) { // $obj *must* have a bar() method
        $obj->bar();
      }
      

      【讨论】:

      • 感谢您的评论,但“我也知道接口基本上允许简单的多重继承行为和设计”,我指的是在编程语言中获得类似行为的能力,例如多重继承t 允许多重继承。没有别的……
      猜你喜欢
      • 2012-05-30
      • 2012-06-01
      • 2011-04-27
      • 1970-01-01
      • 2014-09-10
      • 2015-10-12
      • 2011-12-28
      • 2014-04-29
      相关资源
      最近更新 更多