Luna Tech | OOP Principles

January 2, 2021 字数 1397 3 min


0. 前言

简要介绍面向对象编程的 4 个原则:

  1. Encapsulation
  2. Abstraction
  3. Inheritance
  4. Polymorphism

1. Encapsulation 封装

private vs public

有些东西是别人能看到的,有些是只有自己知道的。

private 的东西自己负责管理,public 的东西可以被别人使用和改变。

object 之间只能通过 public methods 来沟通。

比如:一个人的思想是 private 的,但 TA 说的话是 public 的,别人可以通过和这个人说话来交互,但是不能直接看到这个人脑子里在想什么。

In object-oriented terms, we say that the public members encapsulate the private members of the class.


2. Abstraction 抽象

object 需要把复杂的细节藏起来,只提供别人需要的,而不是全部。

抽象的目的就是让我们可以方便的让别人做一些事情,不需要关心这件事到底是怎么完成的。

比如:

  • 顾客需要知道餐厅的营业时间和菜单,不需要知道餐厅的内部安排和人员分配;
  • 你只需要按开机键就可以打开手机,不需要关注手机到底是怎么启动的;
  • 老板嘱咐下属预订明晚的饭局,不需要知道下属具体是怎么预定的。

因为有了抽象这个概念,我们可以在不影响别人的情况下去修改具体的实现过程,只要最终能达到一样的结果就行了。

比如:

  • 老板让小王去预订饭局,小王让小刘帮忙做这件事,老板最终获得的结果是一样的。

为什么要有封装和抽象呢?

因为当 object 数量越来越多之后,假如每个 object 要关心一大堆跟它无关的事情,就没法集中精力管好自己的事情。

别忘了,程序是人写的,也是需要人去读懂去维护的,假如一个人需要考虑的事情太多了,千条万缕反而会抓不住重点,随着项目规模的扩大,出错的概率也就越大。

程序员们发现让每个 object 各司其职能减少脱发,这也跟我们之前说的 SOLID principle 里面的单一责任有异曲同工之妙(OOP 的项目天生具有 Single Responsibility 的属性呀~)。


3. Inheritance 继承

人们又发现,当两个 object 非常相似(但不完全一样)的时候,假如能够有个继承的概念,就可以减少一大堆的工作量和重复代码。

于是就有了 parent - child 这一对概念,也被称为 base class - subtype class。

child 继承了 parent 的特性,也有自己独特的属性,继承是单向的(也就是 parent 不能继承 child)。

比如:

  • 公立学校和私立学校都是学校,它们有一些共性又不完全一样,那我们就先创建一个学校作为 parent class,然后让公立学校和私立学校成为 child class。

继承的好处就在于我们可以重复使用 parent 的属性,建立不同 class 之间的一种父子关系。

可替换术语

  1. superclass - subclass
  2. parent - child
  3. base - subtype
  4. Is-a relationship (cat is an animal, child is a parent)

4. Polymorphism 多态

当 parent 和 child 对于同一个问题有不同的解决方案时,听谁的?

首先,child 有着 parent 所有的属性(还记得吗?SOLID 里面讲到的 Liskov Substitution Principle 里氏替换原则,就是说 child 可以替换 parent);

其次,在程序运行的过程中,一个 object 可能是被当成 parent 来用的,也可能是被当成 child 来用的,到底是哪个,运行的时候才知道;

比如我们有个 school list,里面有不同的学校类型,由于子类可以替换父类,所以可以用父类来代表 list 里面所有的学校:

1
2
3
4

School[] schools = new School[2];
schools[0] = new PublicSchool();
schools[1] = new PrivateSchool();

School, PublicSchool, PrivateSchool 都有一个 GetEnrollmentFee() 的方法,各自返回不同的结果,子类方法 override 父类方法。

在运行的时候,即使这两个 object 是 School(父类)类型,也会调用子类(PublicSchool、PrivateSchool)里面的方法,因为程序运行时它事实上就是一个子类。

反之,假如子类没有 override 父类方法,那么在运行时会继续使用父类方法。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

// result: 100, 500
void Main()
{
	School[] schools = new School[2];
	schools[0] = new PublicSchool();
	schools[1] = new PrivateSchool();
	
	foreach(School s in schools){
		s.GetEnrollmentFee();
	}
}

class School
{
	public virtual void GetEnrollmentFee(){
		Console.WriteLine("100");
	}
}

class PublicSchool: School{
}

class PrivateSchool : School
{
	public override void GetEnrollmentFee()
	{
		Console.WriteLine("500");
	}
}

简而言之,多态就是指程序在运行中可以判断 object 类型并且根据 runtime object type 来调用方法。


相关文章

Luna Tech | SOLID Principles

参考资料

  1. Polymorphism in C#
  2. How to explain object-oriented programming concepts to a 6-year-old

Talk to Luna


Support Luna