专注Java教育14年 全国咨询/投诉热线:400-8080-105
动力节点LOGO图
始于2009,口口相传的Java黄埔军校
首页 hot资讯 面向对象编程:OOP深入解释

面向对象编程:OOP深入解释

更新时间:2021-08-25 10:49:51 来源:动力节点 浏览883次

什么是面向对象编程?

面向对象编程 (OOP) 是一种依赖于类和对象概念的编程范式。它用于将软件程序构建为简单、可重用的代码蓝图(通常称为类),用于创建对象的单个实例。有许多面向对象的编程语言,包括 JavaScript、C++、Java和Python。

一类是用于创建更具体的,具体对象的抽象蓝图。类通常代表广泛的类别,例如Car或Dog共享属性。这些类定义了此类型的实例将具有哪些属性,例如color,但不定义特定对象的这些属性的值。

类还可以包含函数,称为仅对该类型的对象可用的方法。这些函数在类中定义,并执行一些对特定类型对象有帮助的操作。

例如,我们的Car类可能有一个方法repaint来改变color我们汽车的属性。这个函数只对 type 的对象有用Car,所以我们在Car类中声明它,从而使它成为一个方法。

类模板用作创建单个对象的蓝图。这些代表抽象类的特定示例,例如myCar或goldenRetriever。对于类中定义的属性,每个对象都可以具有唯一值。

例如,假设我们创建一个类,Car以包含所有汽车必须具备的特性color,brand和model。然后我们创建一个Car类型对象的实例,myCar来代表我的特定汽车。

然后我们可以设置类中定义的属性值来描述我的汽车,而不会影响其他对象或类模板。

然后我们可以重用这个类来表示任意数量的汽车。

面向对象的好处

OOP 将复杂事物建模为可重现的简单结构

可重用,OOP 对象可以跨程序使用

允许通过多态实现特定于类的行为

更容易调试,类通常包含所有适用的信息

安全,通过封装保护信息

如何构建 OOP 程序

让我们考虑一个现实世界的问题,从概念上设计一个 OOP 软件程序。

想象一下,经营一个有数百只宠物的狗训练营,您必须跟踪每只宠物的姓名、年龄和参加日期。您将如何设计简单、可重复使用的软件来为狗建模?

有数百只狗,为每只狗编写唯一代码将是低效的。下面我们将看到对象rufus和fluffy.

//Object of one individual dog
var rufus = {
    name: "Rufus",
    birthday: "2/1/2017",
    age: function() {
        return Date.now() - this.birthday;
    },
    attendance: 0
}
//Object of second individual dog
var fluffy = {
    name: "Fluffy",
    birthday: "1/12/2019",
    age: function() {
        return Date.now() - this.birthday;
    },
    attendance: 0
}

正如你在上面看到的,两个对象之间有很多重复的代码。该age()函数出现在每个对象中。由于我们希望每只狗都有相同的信息,因此我们可以使用对象和类来代替。

将相关信息组合在一起形成类结构使代码更短且更易于维护。

在养狗示例中,以下是程序员如何考虑组织 OOP:

为所有狗创建一个父类,作为所有狗都将拥有的信息和行为(方法)的蓝图,无论类型如何。

在通用父蓝图下创建子类来表示狗的不同子类别。

向子类添加独特的属性和行为以表示差异

从代表该子组中的狗的子类创建对象

下图展示了如何设计 OOP 程序:将相关数据和行为组合在一起形成一个简单的模板,然后为专门的数据和行为创建子组。

该Dog班是一个通用模板,只包含有关数据,并适用于所有的狗行为的结构。

然后我们创建两个子类Dog,HerdingDog和TrackingDog。它们具有Dog( bark())的遗传行为,但也具有该亚型狗独有的行为。

最后,我们创建该HerdingDog类型的对象来表示单个狗Fluffy和Maisel。

我们还可以创建这样的对象Rufus,该对象适合广泛的类 ,Dog但不适合HerdingDog或TrackingDog。

面向对象的构建块

接下来,我们将深入了解上面使用的 OOP 程序的每个基本构建块:

班级

对象

方法

属性

班级

简而言之,类本质上是用户定义的数据类型。类是我们为方法和属性的结构创建蓝图的地方。单个对象是从该蓝图实例化或创建的。

类包含属性字段和行为方法。在我们的Dog类示例中,属性包括name& birthday,而方法包括bark()和updateAttendance()。

下面的代码片段演示了如何Dog使用JavaScript语言对类进行编程。

class Dog {
    constructor(name, birthday) {
        this.name = name;
        this.birthday = birthday;
    }
    //Declare private variables
    _attendance = 0;
    getAge() {
        //Getter
        return this.calcAge();
    }
    calcAge() {
        //calculate age using today's date and birthday
        return Date.now() - this.birthday;
    }    
    bark() {
        return console.log("Woof!");
    }
    updateAttendance() {
        //add a day to the dog's attendance days at the petsitters
        this._attendance++;
    }
}

请记住,该类是用于建模狗的模板,并且对象是从代表单个现实世界事物的类实例化的。

对象

当然 OOP 包括对象!对象是使用特定数据创建的类的实例,例如在下面的代码片段中Rufus是Dog类的实例。

class Dog {
    constructor(name, birthday) {
        this.name = name;
        this.birthday = birthday;
    }
    //Declare private variables
    _attendance = 0;
    getAge() {
        //Getter
        return this.calcAge();
    }
    calcAge() {
        //calculate age using today's date and birthday
        return Date.now() - this.birthday;
    }    
    bark() {
        return console.log("Woof!");
    }
    updateAttendance() {
        //add a day to the dog's attendance days at the petsitters
        this._attendance++;
    }
}
//instantiate a new object of the Dog class, and individual dog named Rufus
const rufus = new Dog("Rufus", "2/1/2017");

当新类Dog被调用时:

创建了一个名为的新对象 rufus

构造函数运行name&birthday参数,并分配值

属性

属性是存储的信息。属性在Class模板中定义。当对象被实例化时,单个对象包含存储在 Attributes 字段中的数据。

对象的状态由对象属性字段中的数据定义。例如,在宠物营地,一只小狗和一只狗可能受到不同的对待。生日可以定义对象的状态,并允许软件以不同的方式处理不同年龄的狗。

方法

方法代表行为。方法执行动作;方法可能会返回有关对象的信息,或更新对象的数据。方法的代码在类定义中定义。

当单个对象被实例化时,这些对象可以调用类中定义的方法。在下面的代码片段中,bark方法是在Dog类中定义的,bark()方法是在Rufus对象上调用的。

class Dog {
    //Declare protected (private) fields
    _attendance = 0;
    constructor(name, birthday) {
        this.namee = name;
        this.birthday = birthday;
    }
    getAge() {
        //Getter
        return this.calcAge();
    }
    calcAge() {
        //calculate age using today's date and birthday
        return this.calcAge();
    }
    bark() {
        return console.log("Woof!");
    }
    updateAttendance() {
        //add a day to the dog's attendance days at the petsitters
        this._attendance++;
    }
}

方法经常修改、更新或删除数据。方法不必更新数据。例如,该bark()方法不会更新任何数据,因为 barking 不会修改类的任何属性Dog:name或birthday。

该updateAttendance()方法增加了Dog参加宠物训练营的一天。出勤属性对于在月底跟踪计费所有者很重要。

方法是程序员促进可重用性并将功能封装在对象中的方式。这种可重用性在调试时是一个很大的好处。如果出现错误,只有一个地方可以找到并修复它,而不是很多地方。

下划线 in_attendance表示该变量是受保护的,不应直接修改。该updateAttendance()方法用于更改_attendance.

OOP的四大原则

面向对象编程的四大支柱是:

继承:子类继承父类的数据和行为

封装:在对象中包含信息,只暴露选定的信息

抽象:只公开访问对象的高级公共方法

多态性:许多方法可以完成相同的任务

遗产

继承允许类继承其他类的特性。换句话说,父类将属性和行为扩展到子类。继承支持可重用性。

如果在父类中定义了基本属性和行为,则可以创建子类来扩展父类的功能,并添加额外的属性和行为。

例如,牧羊犬具有独特的放牧能力。换句话说,所有的牧羊犬都是狗,但并非所有的狗都是牧羊犬。我们通过HerdingDog从父类创建一个子类来表示这种差异Dog,然后添加独特的herd()行为。

继承的好处是程序可以创建一个通用的父类,然后根据需要创建更具体的子类。这简化了整体编程,因为子类无需Dog多次重新创建类的结构,而是自动获得对其父类中功能的访问权限。

在下面的代码片段中,子类HerdingDog继承了bark父类Dog的方法,子类添加了一个额外的方法,herd()。

//Parent class Dog
class Dog{
    //Declare protected (private) fields
    _attendance = 0;
    constructor(namee, birthday) {
        this.name = name;
        this.birthday = birthday;
    }
    getAge() {
        //Getter
        return this.calcAge();
    }
    calcAge() {
        //calculate age using today's date and birthday
        return this.calcAge();
    }
    bark() {
        return console.log("Woof!");
    }
    updateAttendance() {
        //add a day to the dog's attendance days at the petsitters
        this._attendance++;
    }
}
//Child class HerdingDog, inherits from parent Dog
class HerdingDog extends Dog {
    constructor(name, birthday) {
        super(name);
        super(birthday);
    }
    herd() {
        //additional method for HerdingDog child class
        return console.log("Stay together!")
    }
}

请注意,HerdingDog该类没有bark()方法的副本,它继承bark()了父Dog类中定义的方法。

当代码调用fluffy.bark()方法时,该bark()方法会沿着子类到父类的链向上走,以找到bark定义方法的位置。

//Parent class Dog
class Dog{
    //Declare protected (private) fields
    _attendance = 0;
    constructor(namee, birthday) {
        this.name = name;
        this.birthday = birthday;
    }
    getAge() {
        //Getter
        return this.calcAge();
    }
    calcAge() {
        //calculate age using today's date and birthday
        return this.calcAge();
    }
    bark() {
        return console.log("Woof!");
    }
    updateAttendance() {
        //add a day to the dog's attendance days at the petsitters
        this._attendance++;
    }
}
//Child class HerdingDog, inherits from parent Dog
class HerdingDog extends Dog {
    constructor(name, birthday) {
        super(name);
        super(birthday);
    }
    herd() {
        //additional method for HerdingDog child class
        return console.log("Stay together!")
    }
}
//instantiate a new HerdingDog object
const fluffy = new HerdingDog("Fluffy", "1/12/2019");
fluffy.bark();

在 JavaScript 中,继承也称为原型设计。原型对象充当另一个对象从中继承属性和行为的模板。可以有多个原型对象模板,创建一个原型链。

这与父/子继承的概念相同。继承是从父到子的。在我们的示例中,所有三只狗都可以吠叫,但只有 Maisel 和 Fluffy 可以放牧。

该herd()方法在子HerdingDog类中定义,因此从该类实例化的两个对象Maisel和可以访问该方法。FluffyHerdingDogherd()

Rufus 是从父类实例化的对象Dog,因此 Rufus 只能访问该bark()方法。

封装

封装意味着将所有重要信息包含在一个对象内部,并且只将选定的信息暴露给外部世界。属性和行为由类模板内的代码定义。

然后,当从类中实例化对象时,数据和方法被封装在该对象中。封装将内部的软件代码实现隐藏在一个类中,隐藏了内部对象的内部数据。

封装需要将某些字段定义为私有字段,将某些字段定义为公共字段。

私有/内部接口:方法和属性,可从同一类的其他方法访问。

公共/外部接口:方法和属性,也可以从类外部访问。

抽象

抽象意味着用户仅与对象的选定属性和方法进行交互。抽象使用简化的高级工具来访问复杂的对象。

用简单的事物来表示复杂性

对用户隐藏复杂的细节

抽象是使用简单的类来表示复杂性。抽象是封装的扩展。例如,您不必了解发动机如何工作来驱动汽车的所有细节。

驾驶员只使用一小部分工具:如油门踏板、刹车、方向盘、闪光灯。工程对司机是隐藏的。为了让汽车运转起来,很多部件都必须在引擎盖下工作,但是将这些信息暴露给驾驶员会很危险地分散注意力。

抽象也起着重要的安全作用。通过只显示选定的数据片段,并且只允许通过类访问数据和通过方法修改数据,我们可以保护数据不被暴露。继续以汽车为例,您不希望在驾驶汽车时打开油箱。

抽象的好处总结如下:

简单、高级的用户界面

复杂代码被隐藏

安全

更轻松的软件维护

代码更新很少改变抽象

多态性

多态意味着设计对象来共享行为。使用继承,对象可以覆盖共享的父行为,具有特定的子行为。多态允许同一个方法以两种方式执行不同的行为:方法覆盖和方法重载。

以上就是动力节点小编介绍的"面向对象编程:OOP深入解释",希望对大家有帮助,想了解更多可查看Java教程。动力节点在线学习教程,针对没有任何Java基础的读者学习,让你从入门到精通,主要介绍了一些Java基础的核心知识,让同学们更好更方便的学习和了解Java编程,感兴趣的同学可以关注一下。

提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>