3.java基本概念

151 阅读9分钟

面向对象编程基本概念

对象

对象是理解面向对象技术的关键。现在环顾四周,你会发现许多现实世界物体的例子:狗、桌子、你的电视机、你的自行车。

现实世界的对象有两个共同的特征:它们都具有状态行为。狗有状态(名称、颜色、品种、饥饿)和行为(吠叫、抓取、摇尾巴)。自行车还具有状态(当前档位、当前踏板踏频、当前速度)和行为(换档、改变踏板踏频、踩刹车)。识别真实世界对象的状态和行为是开始从面向对象编程的角度进行思考的好方法。

现在花一分钟时间观察您附近区域的真实物体。对于你看到的每个对象,问自己两个问题:“这个对象可以处于什么可能的状态?”和“这个对象可以执行什么可能的行为?”。一定要写下你的观察结果。当您这样做时,您会注意到现实世界对象的复杂性各不相同;您的台式机灯可能只有两种可能的状态(打开和关闭)和两种可能的行为(打开、关闭),但您的台式收音机可能具有其他状态(开、关、当前音量、当前电台)和行为(打开、关闭、增加音量、降低音量、搜索、扫描和调频)。您可能还会注意到,某些对象相应的也会包含其他对象。这些真实世界的观察结果都转化为面向对象编程的世界。

image.png

一个软件对象

软件对象在概念上类似于现实世界的对象:它们也由状态和相关行为组成。对象将其状态存储在字段(某些编程语言中的变量)中,并通过方法(某些编程语言中的函数)公开其行为。方法对对象的内部状态进行操作,并作为对象和对象通信的主要机制。隐藏内部状态并要求通过对象的方法执行所有交互称为数据封装——这是面向对象编程的基本原则。

以自行车为例:

image.png

作为软件对象建模的自行车

通过归属状态(当前速度、当前踏板节奏和当前档位)并提供改变状态的方法,对象仍然可以控制外部世界如何使用它。例如,如果自行车只有6个档位,那么换档位的方法可能会拒绝小于1或大于6的任何值。

将代码捆绑到单个软件对象中提供了许多好处,包括:

  1. 模块化:一个对象的源代码可以独立于其他对象的源代码进行编写和维护。对象一旦创建,就可以很容易地在系统内部传递。
  2. 信息隐藏:通过只与对象的方法交互,其内部实现的细节对外部世界是隐藏的。
  3. 代码重用:如果对象已经存在(可能是由另一个软件开发人员编写的),您可以在程序中使用该对象。这允许专家实现/测试/调试复杂的、特定于任务的对象,然后您可以信任这些对象在您自己的代码中运行。
  4. 可插拔性和调试便捷性:如果某个特定对象存在问题,您可以简单地将其从应用程序中删除,并插入另一个对象作为其替代品。这类似于解决现实世界中的机械问题。如果一个螺栓坏了,你要换掉它,而不是整台机器。

在现实世界中,您经常会发现许多相同类型的单个对象。可能还有数以千计的其他自行车,所有自行车的品牌和型号都相同。每辆自行车都是根据同一套模板建造的,因此包含相同的组件。在面向对象的术语中,我们说你的自行车是被称为自行车的对象类的一个实例是用于创建单个对象的模板。 在java文件下新建一个名为day1的包,然后在day1的包里创建Bicycle文件 以下Bicycle类是自行车的代码:

package day1;

class Bicycle {

    int cadence = 0;
    int speed = 0;
    int gear = 1;

    void changeCadence(int newValue) {
         cadence = newValue;
    }

    void changeGear(int newValue) {
         gear = newValue;
    }

    void speedUp(int increment) {
         speed = speed + increment;   
    }

    void applyBrakes(int decrement) {
         speed = speed - decrement;
    }

    void printStates() {
         System.out.println("cadence:" +
             cadence + " speed:" + 
             speed + " gear:" + gear);
    }
}

Java 编程语言的语法对你来说可能看起来陌生,但这个类的设计是基于前面对自行车对象的讨论。字段表示对象的状态(cadence speed gear),方法等定义对象与外界的交互(changeCadence changeGear speedUp)。

您可能已经注意到,该类不包含方法。那是因为它不是一个完整的应用程序;它只是可能在应用程序中使用的自行车模板。应用程序中的其他类负责创建和使用新对象。 在day1包中创建BicycleDemo类,代码如下,创建两个单独的Bicycle对象并调用它们的方法:

package day1;

class BicycleDemo {
    public static void main(String[] args) {

        //创建两个Bicycle对象
        Bicycle bike1 = new Bicycle();
        Bicycle bike2 = new Bicycle();

        // 执行对象的这些方法
        bike1.changeCadence(50);
        bike1.speedUp(10);
        bike1.changeGear(2);
        bike1.printStates();

        bike2.changeCadence(50);
        bike2.speedUp(10);
        bike2.changeGear(2);
        bike2.changeCadence(40);
        bike2.speedUp(10);
        bike2.changeGear(3);
        bike2.printStates();
    }
}

此测试的输出打印两辆自行车的结束踏板踏频、速度和档位:

image.png

继承

不同种类的对象通常彼此之间有一定的共同点。例如,山地自行车、公路自行车和双人自行车都具有自行车的特性(当前速度、当前踏板踏频、当前档位)。然而,每辆自行车都定义了使它们与众不同的附加功能:双人自行车有两个座椅和两组车把;公路自行车有下拉车把;一些山地自行车有一个额外的链环,使它们具有较低的传动比。

面向对象编程允许类从其他类继承常用的状态和行为。在此示例中,现在成为了超类。在 Java 编程语言中,每个类都允许有一个直接超类,并且每个超类(Bicycle) 都有无限数量的子类MountainBike RoadBike TandemBike)的潜力。

image.png

自行车类的层次结构。

创建子类的语法很简单。在类声明的开头,使用 关键字,后跟要从中继承的类的名称:`extends`
package day1;

public class MountainBike extends Bicycle{
    // 这是一个山地自行车,新增了price字段和changePrice方法
    int price = 100;
    void changePrice(int newValue) {
        price = newValue;
    }
}

这里Bicycle提供了相同的所有字段和方法,但允许其代码专注于使其独特的功能。这使得子类的代码易于阅读。但是,必须注意正确记录每个超类定义的状态和行为,因为该代码不会出现在每个子类的源文件中。

接口

我们已经了解了,对象通过它们公开的方法定义它们与外界的交互。方法形成对象与外界的接口;例如,电视机正面的按钮是您与其塑料外壳另一侧的电线之间的接口。您按“电源”按钮打开和关闭电视。

在最常见的形式中,接口是一组具有空体的相关方法。如果将自行车的行为指定为接口,则可能如下所示:

package day1;

public interface BicycleInterface {
    //  车轮每分钟转数
    void changeCadence(int newValue);

    void changeGear(int newValue);

    void speedUp(int increment);

    void applyBrakes(int decrement);
}

要实现此接口,类的名称将更改为ACMEBicycle,并且您将在类声明中使用关键字: implements

package day1;

public class ACMEBicycle implements BicycleInterface{
    int cadence = 0;
    int speed = 0;
    int gear = 1;

    // changeCadence, changeGear, speedUp, applyBrakes全部方法都要实现。
    // 如果这个类中缺少上边的方法,编译将失败。
    @Override
    public void changeCadence(int newValue) {
        cadence = newValue;
    }

    @Override
    public void changeGear(int newValue) {
        gear = newValue;
    }

    @Override
    public void speedUp(int increment) {
        speed = speed + increment;
    }

    @Override
    public void applyBrakes(int decrement) {
        speed = speed - decrement;
    }
    void printStates() {
        System.out.println("cadence:" +
                cadence + " speed:" +
                speed + " gear:" + gear);
    }
}

实现接口允许类在它承诺提供的行为方面变得更加正式。接口在类和外部世界之间形成一个契约,这个契约在构建时由编译器强制执行。如果类声明实现接口,则该接口定义的所有方法都必须出现在其源代码中,然后类才能成功编译。

包是组织一组相关类和接口的命名空间。从概念上讲,您可以将包视为类似于计算机上的不同文件夹。您可以将 HTML 页面保存在一个文件夹中,将图像保存在另一个文件夹中,将脚本或应用程序保存在另一个文件夹中。由于用 Java 编程语言编写的软件可以由成百上千个单独的类组成,因此通过将相关类和接口放入包中来保持组织是有意义的。

Java 平台提供了一个巨大的类库(一组包),适合在您自己的应用程序中使用。该库称为应用程序编程接口,简称API。它的包表示最常与通用编程相关的任务。例如,对象包含字符串的状态和行为;对象允许程序员轻松地创建、删除、检查、比较或修改文件系统上的文件;对象允许创建和使用网络套接字;各种 GUI 对象、控制按钮和复选框以及与图形用户界面相关的任何其他内容。从字面上看,有数以千计的课程可供选择。这使程序员可以专注于特定应用程序的设计,而不是使其工作所需的基础设施。

Java 平台 Java 平台 API 规范提供的所有包、接口、类、字段和方法的完整列表。在浏览器中加载页面并将其添加为书签。作为程序员,它将成为您最重要的参考文档。