
面向对象
面向对象是什么?和面向过程有什么区别?
面向过程(Procedure Oriented) :
核心思想: 自顶向下,逐步细化。将问题拆解成一个个函数(动作),然后按顺序执行。
举例: 比如我想把大象装进冰箱。
面向过程思考的是:“第一步怎么做,第二步怎么做?“
所以面向过程会写出开冰箱门(),放入大象(),关冰箱门()一系列函数。 这些函数是零散的,不聚合的。
缺点: 当系统变大之后(比如我想放河马,放老虎,换个箱子当容器),由于这些步骤之间的耦合度很高,牵一发而动全身,对扩展和维护是及其不好的。
面向对象(Object Oriented):
核心思想: 世界是由对象组成的。我们将数据和行为封装在一起,通过对象之间的交互来解决问题。
举例: 依旧是我想把大象装进冰箱。
面向对象思考的是:”这件事涉及哪些角色?它们各有什么功能?”
所以面向对象会定义出一个个对象:class 冰箱(){属性:颜色,大小;行为:开门(),关门()},class 大象(){属性:体积,重量;行为:走路()}
。执行时,冰箱执行开门,大象执行走路,冰箱执行关门。这样就把冰箱和大象解耦了,以后我们想换个动物,换个容器,只需要改动一处就行了。
缺点:虽然提高了代码复用性、可维护性和扩展性,但它并非完美无缺。面向对象为了实现”分层解耦”
,会让代码变得越来越臃肿,性能开销和系统复杂度也越来越高。就如很多人诟病着Java的迂腐:”为了吃一个鸡蛋,造了一个养鸡场。这种”千斤拨四两”的问题确实是面向对象不得不面对的。
封装、继承和多态
Java 面向对象三大特性的核心:
封装(Encapsulation)
继承(Inheritance)
多态(Polymorphism)
封装(Encapsulation)
对面展示细节,对外暴露接口。
在一个类里,属性是私有的(private),但提供公开的方法(public method)访问。
现在有User 类:
1 | //不封装写法 |
继承(Inheritance)
子类可以拥有父类的属性和方法。
形式:
1 | class 子类 extends 父类 |
先定义父类:
1 | class Car{ |
子类:
1 | class Tesla extends Car{ |
使用:
1 | public class Test { |
运行结果:
1 | 正在行驶 |
子类Tesla通过extends拥有了父类Car的方法,这就是继承。
方法重写(Override)
子类可以重写父类方法。
1 | //在上面的例子中,Tesla是电车,不能够加油,我们想给它充电该怎么办呢?可以重写加油的方法。 |
这就是方法重写。
多态(Polymorphism)
同一个方法,不同对象表现不同。
多态成立有三个条件:
- 继承
- 方法重写
- 父类引用指向子类对象
父类:
1 | class Car{ |
子类:
1 | class Tesla extends Car{ |
使用:
1 | public class Test { |
输出:
1 | Tesla正在充电 |
注意:
1 | Car tesla = new Tesla(); |
变量类型使用的是父类Car,实际对象是Tesla/Maybach
使用时再决定具体调用哪个类。
这就是运行时多态(动态绑定)。
方法重载(Overloading) VS 方法重写(Overriding)
有运行时多态,当然也有编译时多态。它就是方法重载(Overloading)。
方法重载的表现:
同一个方法,不同的参数,表现不同的形式。
1 | class Test { |
可以看到,同一个方法print,传入的参数不同,执行的代码也就不同。
课后问题:
下面的代码如果执行print(1),会发生什么呢?
1 | void print(int a){ |
总结
我们的目标是高内聚,低耦合。
面向对象(Object Oriented Programming) 是一种 以对象为中心的编程思想。
核心思想只有一句话:
把现实世界的事物抽象成对象,通过对象之间的协作完成程序功能。
三大特性:
- 封装,通过访问控制符(public,private)隐藏对象内部实现细节,只暴露必要接口,提高安全性。
- 继承,子类可以继承(extends)父类的属性和方法,实现代码复用。
- 多态,同一方法在不同对象上表现出不同的行为,提高程序扩展性。
面向对象核心的哲学是万物皆对象,用对象来模拟现实世界,每个人负责不同事情,让系统像社会一样协作运行。