【问题标题】:Abstraction in OOPsOOP 中的抽象
【发布时间】:2014-10-02 18:27:12
【问题描述】:

这些年来,我遇到的定义很少,并且从未能够清楚地理解抽象是什么。 我已经理解了 Oops 的 3 个主要概念,但是对于铭刻在这些其他概念中的这个特定概念有困难。

到目前为止,我得出了两个结论,但不确定。

  • 它是一种隐藏方法(行为)的实现细节的能力,只为用户提供接口。
  • 无需实际实现即可定义方法签名(即仅声明它们)。

对于面向对象编程的上下文抽象的正确定义是什么,如果不是上述之一,那么它是什么?

如果还提供支持代码将不胜感激:)

【问题讨论】:

  • 抽象这个词可能太复杂了;水果呢?香蕉是一种水果。苹果是一种水果。水果这个词是一种人们觉得甜的蔬菜的抽象
  • 抽象表示Generalization。就像Fruit 是一个抽象实体,但在现实世界中没有具体的实体叫做水果;而是更具体的水果类型。同样,vehicle 是一个抽象实体,在现实世界中只存在最特定类型的车辆实体。
  • 我最喜欢的关于抽象的文章之一是Zed Shaw's
  • @Rahul:我不同意:抽象并不一定意味着概括:摩天大楼是建筑物(概括),两者都可以建造/实例化。抽象是关于在不允许直接实例化/使用的情况下重新组合行为。抽象需要具体的实现,而泛化不一定需要它。

标签: java c++ oop


【解决方案1】:

它是一种隐藏方法(行为)实现细节的能力,只为用户提供接口。

有点,但那是“封装”。它们是相关的,因为“封装”是面向对象设计的一个关键概念,而“抽象”是该概念的潜在结果。

能够定义方法签名(即仅声明它们)而不实际实现它们。

这是一个实现细节,而不是抽象本身的概念。

在简单的继承模型中,“抽象”可以被认为是通过其祖先(或更抽象的)类型之一来引用对象。例如,考虑一个层次结构:

Lifeform
Animal
Canine
Golden Retriever

如果您正在执行仅针对金毛寻回犬的操作,那么您无法对任何动物执行该操作。它必须是一个特定的动物。所以你需要那个特定的实现。

但是,如果您正在执行对所有 Lifeforms 通用的操作,那么您收到的具体实现并不重要。该操作是抽象的,因此它可以接受任何Lifeform 对象,而不管更具体的实现。

接口提供了另一种可以实现抽象的实现机制。对象组合仍然是另一种机制。例如,考虑这种非继承场景:

public class MyObject {
    private ThirdPartyObject dependency;

    public MyObject() {
        // initialize the dependency
    }

    public boolean getValue() {
        return this.dependency.getValue();
    }

    public void setValue(boolean value) {
        this.dependency.setValue(value);
    }
}

这不使用任何继承或接口,但它确实创建了一个抽象。消费代码对ThirdPartyObject 或其实现细节一无所知。在Law Of Demeter 之后,该实现的细节已被抽象到您控制的自定义对象后面。这对于将您的代码与您无法控制的实现细节分离非常有用。

【讨论】:

  • 照原样,您的示例更多的是关于泛化/专业化而不是抽象。重要的是,如果一个类不能被实例化,那么它就是抽象的。在您的示例中,您不能“实例化”Lifeform,但可以“实例化”Golden Retriever。然而 Life Form 类提供 die() 行为(但不一定定义 Animal、Canine 或 Golden Retriver 将如何 die())
  • @kraal:通常,但不一定。你是对的,在我的例子中,永远不会实例化 Lifeform。在这方面,其他继承层次结构很容易有所不同。更高的层次仍然是更抽象的层次,但作为一个实现细节仍然可以是一个具体的类。
【解决方案2】:

抽象是只显示“相关”数据并“隐藏”用户不必要的对象细节的过程。

  • 例如,当您在线登录您的亚马逊账户时,您输入 你的用户名和密码,然后按登录,当你按时会发生什么 登录,如何将输入数据发送到亚马逊服务器,如何验证 都是从你身上抽象出来的。

  • 另一个抽象的例子:汽车本身就是一个定义明确的 对象,它由其他几个较小的对象组成,例如 传动系统、转向机构、发动机,它们又各有各的 自己的子系统。但是对于人类来说,汽车是一个单一的对象,可以通过其子系统的帮助来管理,即使它们的内部细节 未知。

还需要注意的是,抽象隐藏了实现细节,但可以显示实现,即具有定义的成员函数也可以存在,这与提供全部 抽象接口 不同。

来源:BeginnersBook.com

【讨论】:

    【解决方案3】:

    我的总结是“隐藏细节”;在编程的情况下,抽象更像是您的第一个定义。

    对于支持代码,您真的不需要看得太远。抽象无处不在。考虑通用数据结构string

    计算机中的字符串实际上是转换为特定字符集的字节串在一起。 (没有双关语)

    因此,当您输入"hello, world" 时,它是一个带引号的短语。当计算机运行它时,它会创建一个数据结构string,它本身包含字节和各种状态来表示给定的字符串。 您(通常)不关心string 对象的工作方式。它关心并且您继续实现您的目标。这是我所能得到的抽象示例的基本内容。

    【讨论】:

      【解决方案4】:

      抽象是一个过程,通过该过程,数据和程序以类似于其含义的形式来定义,同时隐藏实现细节。抽象涉及定义表示抽象“参与者”的对象的工具,这些参与者可以执行工作、报告打开并更改它们的状态,并与系统中的其他对象“通信”。

      抽象可以通过两种方式看到:

      数据抽象 - 数据抽象是创建复杂数据类型并仅公开有意义的操作以与数据类型交互的方式,其中向外部工作隐藏所有实现细节。

      控制抽象 - 行为的抽象。提供更简单、更高级别的 API 来隐藏客户端,避免不必要的执行细节。

      【讨论】:

      • 不使用访问说明符等隐藏实现细节封装的定义?
      【解决方案5】:

      抽象是一种承诺实现给定抽象的类将具有给定行为的方法。因此,抽象类不能直接实例化,它们首先需要实现抽象。

      因此,抽象类意味着由一个具体类来实现,该类声明和定义一个与抽象契约匹配的方法。然而,抽象可以提供一些具体的行为以及抽象的行为。

      抽象是通过abstract 类和interface 在Java 中完成的。在 C++ 中,抽象是通过在类中使用 virtual 方法来实现的。请注意,Java 接口仅创建为(与 C++ 不同)该语言不允许多重继承。

      【讨论】:

        【解决方案6】:

        简单来说

        抽象:显示必要的内容并隐藏不必要的细节。例如,如果您的类有 10 个函数,但只有 2 个对类的消费者有用,您将这些函数设为公共而其他是私有的,因此消费者可见的是所需要的,而不是全部显示。

        封装:向类的消费者隐藏复杂性。前任。如果您的类需要两个变量来存储最小值和最大值,则将它们封装在 getter 和 setter 下,并在 getter 和 setter 中实现所有验证和检查。这样你就隐藏了复杂性。

        【讨论】:

          【解决方案7】:

          好吧,我将用一个真实世界的例子来解释抽象。假设在您家中您确实有一个电插头,并且许多设备可以连接到同一个插头,但插头永远不会知道它连接到哪个设备,换句话说,设备的详细信息被抽象(隐藏)到了插头。

          想想如果我们将设备直接连接到没有插头的电线上会怎样?假设将灯泡直接连接到电线,然后电线知道它连接到哪个设备以及何时需要更换灯泡,然后我们必须从灯泡上移除电线连接,这意味着灯泡与电线紧密耦合。换句话说,灯泡和电线知道它所连接的细节,意味着没有抽象。

          在面向对象的世界中,抽象的工作方式完全相同。使用其他类函数/属性的类不需要知道它正在使用哪些类函数/属性,所有内容都应该使用接口/抽象类进行抽象。

          让我编写相同的示例。这里我有一个类“ElectricPlug”,它正在运行一个设备。但是“ElectricPlug”类不知道它正在运行哪个设备。它可以是任何实现接口“IDevice”的类,这意味着“RunDevice”的实现是从“ElectricPlug”中抽象出来的。这是完整的示例代码,

          class Program
          {
              static void Main(string[] args)
              {
                  ElectricPlug electricPlug = new ElectricPlug(new Bulb());
              }
          }
          
          public class ElectricPlug
          {
              private readonly IDevice _device;
              public ElectricPlug(IDevice device)
              {
                  _device = device;
              }
          
              public void Run()
              {
                  _device.Rundevice();
              }
          }
          
          
          public interface IDevice
          {
              void Rundevice();
          }
          
          
          public class Bulb : IDevice
          {
              public void Rundevice()
              {
                 Console.WriteLine("Switched on bulb");
              }
          }
          
          
          public class ElectricPlug
          {
              private readonly IDevice _device;
              public ElectricPlug(IDevice device)
              {
                  _device = device;
              }
          
              public void Run()
              {
                  _device.Rundevice();
              }
          }
          

          【讨论】:

            【解决方案8】:

            oops 中有两部分对象

            • 状态(属性)
            • 行为(方法)

            所以隐藏任何对象的行为实现称为抽象

            举个例子 --> 我家有一个厨师,做美味的食物。有人来我家吃晚饭。晚饭后他们问我这食物是谁做的。我回答了

            • 我有一个厨师,他的名字是tttt,他的地址是tttt,他的号码是0000(这些都是厨师对象的属性)

            他们又问他是怎么做的,然后我回答了

            • 我不知道他是怎么做到的。我只知道他会做菜

            所以抽象意味着我们告诉我们的对象可以执行什么任务,而不是告诉我的对象如何执行任务。

            【讨论】:

              猜你喜欢
              • 2019-12-11
              • 1970-01-01
              • 2014-07-19
              • 2021-09-24
              • 2013-05-30
              • 1970-01-01
              • 2021-07-07
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多