0

当我们谈论概念层面的面向对象编程概念时,假设我们要创建 Car 对象。因此我们需要设计父类。假设如果你要做那部分,你会怎么做?

你会使用类还是接口还是抽象类?那你为什么要使用界面?为什么我们不能对类/抽象类做同样的事情?使用接口作为父级有什么好处?

4

5 回答 5

3

当您不想实例化超类但又想实现一些功能时,您需要抽象类。

单亲继承时需要接口,不能使用抽象类。如果 Java 中存在多重继承,我假设您是根据您使用的术语谈论的,那么接口将是多余的。

于 2012-05-11T16:54:29.587 回答
1

好吧,使用您的 Car 对象,我将尝试通过一个真实世界的示例来解释这个概念。

想象一下,您是一家制造汽车零件的小公司 (A),您为一家较大的公司 (B) 制造汽车零件,该公司是您的客户,这些零件将被其他汽车制造商使用。

B 公司必须确保您的产品符合标准,并且与所有汽车制造商兼容。

这是你的界面。

接口用于定义一些标准化的方法或属性,以我们为例,我们可以定义一块在每个角落有4个孔,用于固定在另一家公司制造的另一块上。

抽象有点不同,抽象比接口更具体(我同意这是一种废话),但它们是具体的,因为它们直接实现(例如接口)功能,而抽象类永远不能 被实例化.

抽象类主要用于定义一些基本或共享的功能以使其干燥。

因此,您可以创建一个扩展抽象类并实现接口的类。

这是一个例子:

interface Vehicle {
   protected $engine;
   protected $wheels;

   public function startUp();
   public function stop();
}

您的 Vehicle 接口定义了需要具有引擎和车轮(任意数量)的 Vehicle。

abstract class Car implements Vehicle {
   protected $wheels = 4;

   public function startUp() {
       $this->engine->startUp();
   }

   public function stop() {
       $this->engine->stop();
   }
}

因为startUp()andstop()只是 Engine 对象的代理,我们可以将它们放在抽象类中,以便在所有扩展类中重用。我们将 Car 类设置为有 4 个轮子。

class Renault extends Car {
   protected $color = 'yellow';
}

这里我们只需要扩展 Car 抽象类,我们添加一些颜色,因为它很酷。

现在,假设我们想把我们的雷诺带到洗车站,因为我们正在实现一个已知的接口,洗车站将能够在不知道我们的车辆是雷诺的情况下工作,但只知道它是一辆车。

这是一个非常基本的示例,它可以设计得更好,但它应该向您展示它是如何工作的。

不需要接口,至少 PHP 不需要任何类来实现任何接口,但是,您应该使用它们,这通常是一种很好的做法,它可以帮助您编写 API、单元测试或在其他开发人员之间共享一些代码。

于 2012-05-11T17:10:11.560 回答
1

冒着变得太深入甚至太夸张的风险,我会尽我所能回答你的问题。

在您提供的示例的上下文中,具有抽象“车辆”类的“汽车”类将是最合适的解决方案。这是因为如果您允许,汽车可以成为一个非常复杂的物体。您可能希望编写一个车辆类来抽象出一些任意的更高级别的数据,而不是将所有内容都打包到汽车类中。如果您计划稍后实现更多功能或创建其他类型的车辆,例如:飞机,这将非常方便。一个抽象类让你的应用程序更加灵活;如果您觉得需要,您还可以抽象车辆类。从概念上讲,OOP 是关于在抽象和分类方面将代码与我们所有人的思维方式联系起来。但是,如果您正在实现简单的功能集,那么简单的类就足够了。

界面是完全不同的野兽。接口(就计算而言)是一种概念工具,允许程序员在实现和应用程序之间创建一个分离层。例如,如果你想创建一些程序来与声卡通信,你应该创建一个接口类。事实上,这本质上就是设备驱动程序。一些语言,如 Java,有一个内置的接口结构来表示相同的概念。但是,理论上您可以使用任何语言创建界面。

您可以使用一个简单的类来实现简单的功能。请记住:类用于对象的实例化;抽象(或基)类用于从类中抽象出数据以创建基本功能。在这两种情况下,它们都处理与应用程序实现不直接相关的代码。但是,这些概念工具不能互换使用。这就是软件工程师和程序员的区别;分别知道何时使用正确的工具和知道如何使用它们。

正如我之前提到的,应该使用接口将实现与应用程序分开。如果您与设备驱动程序通信,您不想混入 GUI 代码。接口就像两者之间的联络人。从技术上讲,接口是“实现”的,而不是继承自;然而,在没有明确接口结构的语言中,类用于模拟概念,因此将被继承。

于 2012-05-11T17:47:36.103 回答
0

我有一个简单的解释,假设你有一个扩展 A 的 B 类。现在你想在 B 类中进行克隆或者你想进行排序。那么现在你会做什么?如果你已经创建了一个 Clonable 类/Comparable 类,你如何在 B 中使用它,因为 B 已经扩展了 A。所以你的解决方案是创建另一个扩展可克隆类的 D 类。创建另一个扩展 D 的类 E(以使用克隆方法)然后....意味着因为java不支持多重继承,所以您必须不使用任何类来执行dis..但是当您将Clonable定义为接口时,您不需要做的只是在Ur中实现它B 类。即不需要额外的编码。这是我为什么要制作接口的解释。如果我在某处错了,请纠正我。谢谢。

于 2013-05-22T09:57:50.163 回答
0
  • 抽象类。

当您有一些概括其他实体但没有“现实世界”化身的概念时,抽象类很有用。

假设您Car的程序中有类,并且您将拥有HummerH2,ToyotaCamryDaewooMatiz派生自Car. CarSome-Abstract-Car,任何汽车都属于Car类,但Car类本身并不表示任何真正的汽车。

所以你可以定义Car类如下:

abstract class Car
{
    public abstract void Move();
    public abstract void Stop();
    public abstract int GetMaximumSpeed();
    public int GetVehicleID()
    {
        return vehicleID;
    }


    protected int vehicleID;
}

然后派生出你HummerH2ToyotaCamryDaewooMatizCar和实施Move()Stop()GetMaximumSpeed()那里。请注意,Car类将强制其子类具有vehicleID字段。

  • 接口

接口类似于抽象类,只是不能在接口中声明字段。接口用于声明类必须实现的一些公共功能。

在我们的例子中,我们可以声明接口 IMovable:

interface IMovable
{
    void Move();
    void Stop();
    abstract int GetMaximumSpeed();
}

然后从 IMovable 继承 Car 类:

abstract class Car: IMovable
{
    public int GetVehicleID()
    {
        return vehicleID;
    }
    protected int vehicleID;
}

请注意,现在Car 必须实现的子类Move()Stop()方法。

而且我们可以定义一些Ship将实现IMovable接口的类。在这种情况下,无论它是汽车还是轮船或任何实现接口,两者ShipCar可以作为对象移动,而无需任何对象。IMovableIMovable

PS:当然,当您编写一些只有一种汽车的简单游戏时,您可以定义非抽象类Car并使用它。

于 2012-05-11T17:32:25.287 回答