Java中的OOP--抽象和封装入门教程

292 阅读9分钟

Java中的OOP--抽象和封装入门

面向对象编程(OOP)是一种编程范式(方法),或者说和程序化编程一样。与程序性编程不同的是,我们将一切都建模为对象(现实生活中的实体)。Java,作为一种面向对象的编程语言,被设计为遵循这种模式。

对象来自于类,是一种泛化的形式,但一个真实的东西就是一个对象。到底什么是类?一个类是一个创建对象的模板。

从一个类中创建对象的过程称为实例化。

在本教程中,读者将了解到抽象、封装、对象和类。对于绝对的Java初学者来说,OOP的概念将是一块不错的抓手。

前提条件

读者应具备以下条件

  • 至少有Java的基本知识。
  • 在你的电脑上安装了Java。
  • 拥有你选择的任何IDE。

目标

在本OOP教程系列结束时,读者应该能够。

  • 区分类和对象。
  • 理解抽象和封装。
  • 从类中创建对象。
  • 对OOP的内容有一定的了解。
  • 创建抽象的类和接口。

类是创建对象的一个模板或蓝图。为了表示属性或特性,类使用实例变量,而对于行为或动作,它使用实例方法。

实例变量

这些是在类中声明的变量,在方法和构造函数之外。实例变量有一个全局范围。

实例方法

这些是只有其类的对象才能调用的方法。是类定义了一个对象的数据字段或变量和方法的内容。

一个类的例子是一个圆类。一个圆有一个半径,我们可以从中创建不同类型的圆的对象。下面的代码片断解释了这个想法。

 
public class Circle {

    //instance variable

    private double radius = 2.5;

    //no-argument constructor

    public Circle() {

    }

    //argument constructor

    public Circle(double radius) {
        this.radius = radius;
    }

    //method

    public double getArea() {
        return Math.PI * radius * radius;
    }

    //method

    public double getPerimeter() {
        return Math.PI * (2 * radius);
    }

}
 

通过这个,我们创建了一个叫做Circle的类。其他类也是如此,如汽车、人类、动物等。简单来说,一个类就是一个模型。

对象

对象是一个实际的实体,其属性和行为由其模型定义,如圆、狗、鱼、人等。现在我们已经创建了一个圆的模板,创建不同大小的圆就变得容易了。

 
public class CircleSize {

    //entry point to every Java application

    public static void main(String[] args) {

        Circle smallCircle = new Circle();

        /*The new keyword used here means a new object of type class is created and saved in the variable smallCircle of reference type Circle*/

        //to get the area of the circle created

        System.out.println("The area of this circle is " + smallCircle.getArea());

        /*you can also decide to use an arg constructor to construct your new circle*/

        Circle bigCircle = new Circle(2.5);

        System.out.println("The area of this circle is " + bigCircle.getArea());

    }

}
 

如果你想创建一个狗类型的对象,同样的事情也适用。狗应该有一个名字、颜色、年龄和品种。狗应该能够睡觉、吃饭、跑步或吠叫。

 
public class Dog {

    private String name;

    private int age;

    private String color;

    private String breed;

    //Dog arg constructor

    public Dog(String name, int age, String color, String breed) {

        this.name = name;

        this.age = age;

        this.color = color;

        this.breed = breed;

    }

    public boolean isSleeping() {

        System.out.println("Sleeping");
        return true;
    }

    public boolean isEating() {

        System.out.println("Eating");
        return true;

    }

    public boolean isbarking() {

        System.out.println("Dog barking...");
        return true;
    }

    public boolean isRunning() {

        System.out.println("Dog running");
        return true;
    }

}
 

要创建一个新的狗对象。

 
public class Dog_Main {

    public static void main(String[] args) {

        Dog littleDog = new Dog("Bingo", 6, "Brown", "German Shepherd");

        System.out.println("Is the dog running:? " + littleDog.isrunning());

        System.out.println();

        System.out.println("is the dog sleeping:? " + littleDog.isSleeping());

        System.out.println();

        System.out.println("Is the dog barking:? " + littleDog.isbarking());

        System.out.println();

        System.out.println("Is the dog eating:? " + littleDog.iseating());

        System.out.println();

        System.out.println("The dog name is:  " + littleDog.name);

    }

}
 

现在你看到了,我们已经创建了一只新的狗,名字是Bingo 。你可以继续创建尽可能多的具有不同状态或属性的狗。

下面是输出结果。

  Dog running
 
  Is the dog running:? true
 
  Sleeping
 
  is the dog sleeping:? true
 
  Dog barking...
 
  Is the dog barking:? true
 
  Eating
 
  Is the dog eating:? true
 
  The dog name is: Bingo

现在我们把这个问题解决了,让我们来谈谈抽象和封装的问题。

抽象

谁能想象到抽象会成为编程中的一个东西?谁?但是现在,你在谈论OOP的时候不能不提到抽象。

它是OOP的一个重要构件。那么,什么是抽象?本节将解释什么是抽象以及作为一个Java开发者如何使用它。

在抽象中,只有对象的有用属性才会被显示或被访问。低层次的细节被隐藏起来。例如,想象一下你在电脑上打字。

你对打字感兴趣,相信它能在你的屏幕上产生结果。你对产生结果的机制一无所知,而且我肯定你甚至还没有想过这个问题。你有吗?

这里有另一个例子可以让事情更清楚:想象一下汽车司机。他们只对汽车的启动、移动和停止、速度、或换挡和刹车感兴趣。

他们对允许他们这样做的机制不感兴趣。在抽象中,我们向用户隐藏了实现细节,同时暴露了功能。

这样,用户只知道一个函数(java中的方法)做什么,而不知道它是如何做的。

如何在Java中实现抽象

在Java中,抽象是用这两种方式中的一种实现的。

  1. 通过使用非访问修改器abstract关键字或
  2. 接口

使用Abstract关键字工作

你只能对类和方法使用抽象访问修饰符关键字,但不能对变量使用。带有关键字abstract的方法是没有实现的方法。

要在Java中实现一个抽象类,请使用抽象关键字,例如:public abstract class Circle ,其中Circle是类名。

让我们用这个代码片断来演示一下。

 
public abstract class Dog {

    public abstract void run();

}
 

通过上面的代码片断,我们已经创建了一个抽象类和一个抽象方法。抽象类的一个相关特征是,对象不能被实例化或从它创建。但是别忘了,类的存在只是为了创建一个对象。

为了能够从一个抽象类中创建一个对象,我们必须创建一个继承自超类(基类/父类)的新类。

你可以使用extends 关键字来做到这一点。实现抽象方法是为了避免编译器在抽象方法没有实现时抛出的编译错误。

下面是一个说明extends 关键字的代码片断。

 
public class MainDog extends Dog {

    //abstract method body definition
    @Override
    public void run() {
        //in this class the method is implemented
        System.out.println(“Dog is running”);

    }

    public static void main(Strings[] args) {

        MainDog dog = new MainDog();

        //abstract method invocation

        dog.run();

    }

}
 

接口的实现

一个接口包含公共的、抽象的方法签名(没有实现的方法)。还需要注意的是,接口没有构造函数,可能包含最终变量和静态变量。

通过使用implements 关键字,通过接口方法实现抽象是可能的。由于接口中的方法没有主体,实现它的类必须实现接口中的所有方法。子类继承父类,重写其方法签名,并提供一个方法体。

 
public interface Car {

    public void start();

    public void stop();
}

public Benz implements Car {

    /*This stop method will execute independent of the @Override annotation but the annotation tell the compiler we are overriding a superclass method*/

    @Override
    public void start() {
        System.out.println(“I started my Benz car”);
    }

    /*This stop method will execute independent of the @Override annotation but the annotation tell the compiler we are overriding a superclass method*/

    @Override
    public void stop() {
        System.out.println(“I stopped my Benz car”)
    }

}
 

为了运行这个程序,我们需要另一个类和main方法。后者是每个Java应用程序的入口。

 
public class Main {

    public static void main() {

        Car car = new Benz();

        car.start();

        car.stop();

    }

}
 

在主方法中,Car 代表接口类,Benz 代表具体类或子类。子类将其内存交给Car 对象,以访问其实现的方法。

Benz 类以它想要的方式实现了Car 类的启动和停止行为。这使我们的应用程序变得稳健。我们可以在不破坏应用程序的情况下,改变或增加对我们应用程序的要求。

例如,我们想添加另一辆汽车,以不同的方式停止或启动。我们可以创建一个汽车,例如:Toyota ,实现类Car ,重写其stop()start() 方法,然后以我们希望我们的Toyota 启动和停止的方式实现它们。

只要有新的要求,就不需要进入Car 类来改变我们的代码。现在,我们终于把抽象问题解决了,接下来就是下一个问题,封装。

封装

想象一下,你正在构建一个应用程序,而用户可以直接访问和操作你的数据字段。那会有多大的代价?其结果最好留待想象,而不是体验。

除了我将在下一篇文章中写到的继承和多态之外,封装是每个开发者都需要熟悉的另一个OOP的基本概念。

封装是简单地将类的实现细节封装起来并隐藏起来,使之不被用户发现的过程。封装是通过将类的属性或变量和方法包装成一个单元来实现的。

封装可以保证应用程序的安全,因为程序的用户不能访问私有变量。他们只能使用其公共方法,通常是访问器和突变器方法。

访问器方法

这些方法在被调用时可以访问一个类的私有变量。

突变器方法

这些方法在被调用时可以对私有变量进行设置或赋值。

让我们用下面这个简单的代码片断来解释一下。

 
public class Human {

    private String name;

    private int age;

    private String gender;

}
 

在上面的代码片断中,我们将类的所有字段和属性都声明为私有。这样一来,客户端或用户只能使用访问器或突变器方法来访问它们。

访问器和突变器方法被称为gettersetter方法。因此,例如,要从Human 类中设置和获取一个对象的名称,在Human 类中声明以下方法。

 
public void setName(String name) {
    this.name = name;
}

public String getName() {
    return name;
}
 

由于这些方法是公开的,只要从Human类中创建一个对象,其他类就可以设置和获取名称。封装通过减少客户对我们的数据或类契约的访问方式来保证我们的代码安全。

你可以使用这两个步骤来实现封装。

  1. 像我们在上面的代码中那样,将类的属性声明为私有。
  2. 提供公共的setter和getter方法。

抽象和封装之间的区别

抽象和封装之间的明显区别是。

  • 抽象隐藏了程序的内部细节,只显示功能。
  • 封装将代码和数据都包裹起来。
  • 抽象隐藏了复杂性,而封装隐藏了内部工作。

总结

在这篇文章中,我们已经学习了抽象和封装的概念,如何声明一个类和创建一个对象。

我们谈到了如何实现抽象和封装,我们也看到了抽象和封装的区别。