OOP 抽象 vs 封装多重定义

OOP abstraction vs encapsulation multiple definitions

在阅读不同来源的封装和抽象定义时,我越来越困惑。真的很难决定哪个是正确的定义。

封装定义1

Encapsulation : Encapsulation is the technique of making the fields in a class private and providing access to the fields via public methods

封装定义2

Encapsulation is the procedure of covering up of data and functions into a single unit (called class).

抽象定义 1

Abstraction is a way of modelling a real world object with minimal information.

抽象定义 2

Exposing only the methods which are necessary.

请帮助我理解这些与 OOP 相关的词的正确定义。解释正确定义的书籍的来源也是首选。

谈到代码,抽象 只是一段描述真实世界的代码"thing"。大多数时候你无法描述整个 "thing",但你可以描述它的主要特征,在你的代码中,这将被称为 attributes.

一个抽象的例子是餐馆:你去,你要菜单和 select 你想吃的任何东西......但你 不吃纸:你select你想要什么看它的抽象(菜单)......那个抽象可能只是说"Eggs & Bacon",但是当服务员给你点菜时它有一对鸡蛋(炒)、两片脆皮培根和其他一些东西...菜单只是 真实 东西的简单抽象。

Bicycle example in the Java Tutorials:自行车有属性:

  1. 速度
  2. 齿轮
  3. 节奏

您(在此示例中)对自行车的任何其他特征不感兴趣...所以这是一个抽象。

现在,关于封装:在编写代码时,您希望修改对象的属性只能以"propper"方式:如果你改变速度(再次以自行车为例),你可能还必须改变节奏 and/or 改变齿轮。因此,您声明属性 private 并仅通过 public 方法更新它们,并且在这些方法中,您确保所有属性都具有一致的值:

public class Bicycle {
    private int speed, gear, cadence;
    /**
     * Default constructor
     */
    public Bicycle() {
        speed = 0;
        gear = 1;
        cadence = 0;
    }
    /**
     * An example 
     */
    public void setSpeed(int speed) {
        this.speed = speed;
        /*
           You can set the value of the other attributes here if you want to
         */
    }
    /**
     * Another example
     */
    public void gearUp() {
        if(gear < 5)
            gear++;
        /*
           Here you are preventing other methods to set the gear to
           a value higher than 5.
         */
    }
    /**
     * Another one
     */
    public void gearDown() {
        if(gear > 1)
            gear--;
        /*
           Here you are preventing other methods to set the gear to
           a value lower than 1.
         */

    }
}

以下面的两个代码片段为例:

// Snippet #1
public static void Main(){
    int sum = 0;
    for (int i = 0; i <= 1000; i++) {
        sum += i;
    }
    System.out.println(sum);
}

在上面的代码片段中,您的程序正在计算从 0 到 1000 的所有整数的总和。您可以看到计算是如何完成的,并且您可以控制存储总和值的变量.

// Snippet #2

public class Adder {
    private int sum;

    public Counter(){
        this.sum = 0;
    }

    public void add(int value){
        this.sum += value;
    }

    public int getSum(){
        this.sum;
    }
}

public static void Main(){
    Adder adder = new Adder();
    for (int i = 0; int <= 1000; i++) {
        adder.add(i);
    }
    System.out.println(adder.getSum());
}

上面的代码片段执行相同的任务,但有所不同。有一个 class 提供了您所质疑的两个特征。它提供了一个抽象来系统地添加数字,并且封装如何进行计算的细节。换句话说,它将添加数字的关注点及其工作方式与将数字从 0 迭代到 1000 的任务(在 Main 函数中)分开了。

在这个例子中:

  • abstraction是相加数的概念,所以对于每一种不同的类型,你会有不同的abstraction想法

  • encaptulation是实现细节与主程序的分离。也就是说,您可以为相同类型的抽象创建一个新的 class 但使用不同的实现(long 而不是 un int,例如)。

抽象
抽象与将方法设为私有或 public 无关。它与识别类型 class 共有哪些功能有关。

在 java 中,抽象 class 比接口更进一步。在界面中说 class 类型 X 必须执行 X、Y、Z。 X、Y、Z 可以按您选择的任何方式实施。

抽象 class 说 class 类型 X 必须执行 X、Y、Z,但是标记为抽象的方法必须以特定方式完成,因此它在抽象中实现 class(抽象)。

封装
它只是将一个或多个东西包裹在另一个东西中。简化或隐藏代码。您为什么要这样做的一个示例是简化流程。例如,如果您希望用户能够关闭计算机,您可以有一堆方法供某人显式调用:

Util.shutdownApps();
Util.shutdownServices();
Util.shutdownScreenAndKeyboard();
Util.poweroff();

如果您想以特定方式关闭或只是让别人更容易关闭您可以封装它:

Util
    public void shutdown(){
    Util.shutdownApps();
    Util.shutdownServices();
    Util.shutdownScreenAndKeyboard();
    Util.poweroff();
    }

  private shutdownApps(){...}
  private shutdownServices(){...}
  private shutdownScreenAndKeyboard(){...}
  private poweroff(){...}