为什么我们在拥有Class时需要抽象类?

时间:2012-05-11 16:52:07

标签: oop class interface conceptual

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

你会使用Class或接口或抽象类吗? 那为什么要使用界面? 为什么我们不能用class / Abstract类做同样的事情? 使用interface作为父级有什么好处?

5 个答案:

答案 0 :(得分:3)

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

当您具有单父继承时,

需要接口,并且您不能使用抽象类。如果Java中存在多重继承,我假设您根据所使用的术语进行了讨论,那么接口将是多余的。

答案 1 :(得分:1)

好吧,使用你的Car对象,我将尝试用一个真实世界的例子解释这个概念。

想象一下,你是一个小公司(A)制造汽车零件,你为一个更大的公司(B)制造它们是你的客户,这些零件将被其他汽车制造商使用。

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

这是你的界面。

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

抽象有点不同,抽象比界面更具体(我同意这是一种无意义的),但它们是具体的,因为它们直接实现(例如一个接口)功能,而Abstract类可以从不实例化。

抽象类主要用于定义一些基本或共享功能,使其成为DRY。

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

以下是一个例子:

interface Vehicle {
   protected $engine;
   protected $wheels;

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

您的车辆界面定义了一辆需要引擎和车轮(任意数字)的车辆。

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

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

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

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

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

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

现在,让我们说我们想将雷诺带到洗车站,因为我们正在实施一个已知的界面,洗车站将能够在不知道我们的车辆是雷诺的情况下完成工作,但只是知道它是一辆车。

这是一个非常基本的例子,它可以更好地设计,但它应该告诉你它是如何工作的。

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

答案 2 :(得分:1)

冒着太深的风险,可能太过戏剧化,我会尽力回答你的问题。

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

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

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

如前所述,接口应该用于将实现与应用程序分开。如果您与设备驱动程序通信,则不希望混合GUI的代码。界面就像两者之间的联络。从技术上讲,接口是“实现”的,不是继承自的;但是,在没有明确的接口构造的语言中,一个类用于模拟概念,因此将继承。

答案 3 :(得分:0)

  • 抽象类。

当你有一些概念推广其他实体但没有'真实世界'的化身时,抽象类很有用。

假设您的计划中有Car个班级,那么您将从HummerH2派生ToyotaCamryDaewooMatizCar个班级。 Car Some-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;
}

然后从HummerH2派生ToyotaCamryDaewooMatizCar,并在那里实施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都可以作为IMovable对象移动,无论是汽车还是船舶,还是实施IMovable接口的任何内容。

P.S。:当然,当你编写一个只有一种类型汽车的简单游戏时,你可以定义非抽象类Car并使用它。

答案 4 :(得分:0)

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

相关问题