CodeGym/Java 博客/随机的/面向对象原则
John Squirrels
第 41 级
San Francisco

面向对象原则

已在 随机的 群组中发布
个会员
你好!在今天的课程中,我们将讨论面向对象编程的原则。您是否想过为什么 Java 的设计完全如此?我的意思是,你声明类并基于类创建对象,类有方法等等。但是为什么语言的结构使得程序由类和对象组成,而不是其他东西?为什么要发明“对象”的概念并将其放在首位?所有的语言都是这样设计的吗?如果不是,它给 Java 带来了什么优势?如您所见,有很多问题 :) 让我们在今天的课程中尝试回答每个问题。

什么是面向对象编程 (OOP)?

当然,Java 并不是为了好玩而由对象和类组成的。它们不是 Java 的创造者心血来潮,甚至不是他们的发明。还有许多其他基于对象的语言。第一种这样的语言被称为“Simula”。它于 1960 年代在挪威发明。更重要的是,Simula中出现了“类”和“方法”的概念。以软件开发的标准来看,“Simula”似乎是一门古老的语言,但任谁都能看出它与Java的“血缘”。面向对象编程原理 - 1您可能可以轻松阅读用这种语言编写的代码,并粗略地解释它的作用 :)
Begin
	Class Rectangle (Width, Height); Real Width, Height;

	 Begin
	    Real Area, Perimeter;

	    Procedure Update;
	    Begin
	      Area := Width * Height;
              OutText("Rectangle is updating, Area = "); OutFix(Area,2,8); OutImage;
	      Perimeter := 2*(Width + Height);
              OutText("Rectangle is updating, Perimeter = "); OutFix(Perimeter,2,8); OutImage;
	    End of Update;

	    Update;
	    OutText("Rectangle created: "); OutFix(Width,2,6);
	    OutFix(Height,2,6); OutImage;
	 End of Rectangle;

       Rectangle Class ColouredRectangle (Color); Text Color;

	Begin
	    OutText("ColouredRectangle created, color = "); OutText(Color);
	    OutImage;
        End of ColouredRectangle;


      	 Ref(Rectangle) Cr;
	 Cr :- New ColouredRectangle(10, 20, "Green");
End;
本代码示例代码摘自Weekly-geekly的《Simula - 50 years of OOP》。如您所见,Java 与它的祖父并没有太大区别:) 这是因为 Simula 的出现标志着一个新概念的诞生:面向对象编程。维基百科是这样定义 OOP 的:“面向对象编程 (OOP) 是一种基于“对象”概念的编程范式,它可以包含数据,以字段(通常称为属性)的形式,以及代码,以形式程序(通常称为方法)。” 在我看来,这是一个非常好的定义。不久前您开始学习 Java,但是这个定义可能不包含任何您不知道的词 :) 今天 OOP 是最常见的编程方法论。除了Java,OOP 原则用于您可能听说过的许多流行语言。例如,C++(积极用于游戏开发)、Objective-C 和 Swift(用于为 Apple 设备编写程序)、Python(在机器学习中最流行)、PHP(最流行的 Web 开发语言之一)、JavaScript(更容易说出它不用于什么)和许多其他。那么,OOP 的原则到底是什么?我们会详细告诉你。OOP 的原则是什么?我们会详细告诉你。OOP 的原则是什么?我们会详细告诉你。

面向对象原则

这些是基础的基础。4 个主要特征共同构成了面向对象的编程范式。了解它们对于成为一名成功的程序员至关重要。

原则 1. 继承

好消息:您已经了解 OOP 的一些原则!:) 我们已经在课程中遇到过几次继承,并且我们设法使用了它。继承是一种机制,可让您基于现有(父)类描述新类。这样做时,新类借用了父类的属性和功能。什么是继承,它提供了哪些优势?最重要的是,代码重用。父类中声明的字段和方法可以在子类中使用。如果所有类型的汽车都有10个公共字段和5个相同的方法,则只需将它们移动到Auto父类。您可以毫无问题地在子类中使用它们。坚实的优势:既有定量的(更少的代码),也有定性的(类变得更简单)。此外,继承非常灵活——您可以添加后代所缺少的单独功能(某些特定于特定类的字段或行为)。总的来说,就像在现实生活中一样,我们都与我们的父母有些相似,但也与他们有所不同 :)

原则 2. 抽象

这是一个非常简单的原则。抽象意味着确定事物的主要、最重要的特征,同时丢弃任何次要和无关紧要的事物。无需重新发明轮子。让我们回忆一下关于类的旧课中的一个例子。假设我们正在为公司员工创建一个文件系统。为了创建“雇员”对象,我们编写了一个雇员类。在公司备案系统中描述它们的哪些特征很重要?姓名、出生日期、SSN 和员工 ID。但我们不太可能需要员工的身高、眼睛颜色或头发颜色来进行此类记录。公司不需要有关员工的此类信息。因此,在Employee类中,我们声明了以下变量:, int age , int socialSecurityNumberint employeeId。我们抽象掉了不必要的信息,比如眼睛的颜色。但是,如果我们正在为模特经纪公司制作归档系统,情况就会发生巨大变化。模特的身高、眼睛颜色和头发颜色是重要的特征,但她的 SSN 与我们绝对无关。因此,在Model类中,我们创建了以下变量:String heightString hairString eyes

原则 3. 封装

我们已经遇到过这个。在 Java 中,封装意味着限制读取和更改数据的能力。如您所见,该术语基于“胶囊”一词。我们将使用“胶囊”来隐藏一些我们不希望其他人更改的重要数据。这是现实生活中的一个简单例子。你有名字和姓氏。你所有的朋友都认识他们。但他们无法更改您的名字或姓氏。我们可以说这样做的过程被法院系统“封装”了:您只能通过法院书记员更改您的姓氏,而且只有您自己可以这样做。其他“用户”对您的名字和姓氏具有“只读”访问权:) 另一个说明性示例是存放在家里的现金。将它放在房间中央的显眼位置并不是一个好主意。任何“用户”(来到您家的人)都可以更改您的钱数,即他们可以拿走您的钱。还是封装在保险柜里比较好。然后只有您才能访问,并且只能使用特殊代码。您已经使用过的明显封装示例是访问修饰符(私有、公共等),以及 setter 和 getter。如果你不封装Cat类的age字段,那么任何人都可以写:
Cat.age = -1000;
封装机制让我们用setter方法保护age字段,保证age不能设置为负数。

原则 4. 多态性

多态性是处理多种类型的能力,就好像它们是同一类型一样。此外,对象的行为将根据它们的类型而有所不同。这听起来很复杂吗?让我们现在就理解它。举个最简单的例子:动物。使用单个speak()方法和两个子类—— CatDog创建一个Animal类。
public class Animal {

   public void speak() {

       System.out.println("Hello!");
   }
}

public class Dog extends Animal {

   @Override
   public void speak() {
       System.out.println ("Woof-woof!");
   }
}

public class Cat extends Animal {

   @Override
   public void speak() {
       System.out.println("Meow!");
   }
}
现在我们将尝试声明一个Animal引用变量并为其 分配一个Dog对象。
public class Main {

   public static void main(String[] args) {

       Animal dog = new Dog();
       dog.speak();
   }
}
你认为会调用什么方法?Animal.speak()Dog.speak()Dog类中的方法将被调用:Woof-woof!我们创建了一个Animal引用,但该对象的行为类似于Dog。如有必要,它可以表现得像猫、马或其他动物。重要的是将特定的子类分配给一般的Animal引用变量。这是有道理的,因为所有的狗都是动物。这就是我们所说的“对象的行为会因类型而异”时的想法。如果我们创建了一个Cat对象......
public static void main(String[] args) {

   Animal cat = new Cat();
   cat.speak();
}
speak ()方法会显示“Meow!” 但是,我们所说的“像处理同一类型一样处理多种类型的能力”是什么意思?这也很简单。假设我们正在为动物创建一个理发店。我们的理发店应该能够给任何动物修剪,所以我们创建了一个带有Animal参数(正在理发的动物) 的trim()方法。
public class AnimalBarbershop {

   public void trim(Animal animal) {

       System.out.println("The haircut is done!");
   }
}
现在我们可以将CatDog对象传递给trim()方法!
public static void main(String[] args) {

   Cat cat = new Cat();
   Dog dog = new Dog();

   AnimalBarbershop barbershop = new AnimalBarbershop();

   barbershop.trim(cat);
   barbershop.trim(dog);
}
这是一个明显的例子:AnimalBarbershop类与CatDog类型一起工作,就好像它们是同一类型一样。同时,CatDog有不同的行为:他们说话的方式各不相同。

为什么我们需要 OOP?

为什么 OOP 会作为一个新的编程概念出现?程序员拥有功能性工具,例如过程语言。是什么促使他们发明了一些全新的东西?最重要的是,他们面临的任务非常复杂。如果 60 年前程序员的任务类似于“评估一些数学表达式”,那么现在它可能类似于“根据玩家在 A、B、C、DE 点做出的决定的组合,为游戏 STALKER 实现 7 个不同的结局, 以及游戏中的 F。” 如您所见,在过去几十年中,任务显然变得更加复杂。结果,数据类型变得更加复杂。这也是OOP出现的另一个原因。可以使用普通原语轻松计算数学表达式。这里不需要对象。但是如果不使用自定义类,游戏结局的任务甚至很难描述。也就是说,使用类和对象来描述它非常容易。显然,我们需要几个类:Game、Stalker、Ending、PlayerDecision、GameEvent 等等。换句话说,即使没有开始解决问题,我们也可以很容易地在脑海中“勾勒出”一个解决方案。任务越来越复杂,迫使程序员将它们分成几部分。但这在过程编程中并不是那么容易做到。一个程序通常就像一棵树,有很多分支代表所有可能的执行路径。根据某些条件,执行程序的一个分支或另一个分支。对于小程序来说,这很方便,但是很难将一个大问题分成几个部分。这是 OOP 出现的另一个原因。这种范式使程序员能够将程序划分为一堆“模块”(类),每个模块都完成自己的部分工作。通过相互交互,所有对象完成我们程序的工作。另外,我们可以在程序的其他地方复用我们的代码,这也节省了大量的时间。
评论
  • 受欢迎
你必须先登录才能发表评论
此页面还没有任何评论