简单理解面向对象
1. 对象与类
万物皆是对象,而你还没有对象🐶。 --尼采(啥都是俺说的)
我们可以用生活中常见的表格来理解对象。
如下是个学生信息表:
班级 | 学号 | 姓名 | 技能 |
---|---|---|---|
301 | 10001 | 小对 | 学习、打篮球 |
301 | 10002 | 小象 | 学习、踢足球 |
302 | 10003 | 小象 | 学习、打篮球 |
表中的第2-4行即可看作是3个不同的对象(Object)。
上表的第一行(<“班级”、“学号”、“姓名”、“技能">这个整体)可以看作是类(Class),而“班级”、“学号”、“姓名”这些列我们称之为属性or字段(field),“技能”这一列我们称之为方法(method)。
将上表转为类:
class Student{
int classID; //班级
int ID; //学号
String name; //姓名
void study(...){...}; //学习
void sport(...){...}; //运动,包括打篮球、踢足球等
public Student(...){...}; //构造方法,目的是创造对象
}
类与对象的关系:类进行实例化得到对象。类是图纸,对象是根据图纸造出来的实体。
2. 面向对象与面向过程的区别
-
面向过程:将解决问题的过程拆分为一步步并实现。
- 经典问题:把大象塞进冰箱需要几步?……
- 扮演角色:执行者
- 适用于:解决简单的、无需协作的问题
- 编程语言代表:C语言
-
面向对象:如何将目标事物设计出来,将其属性和方法定义并实现。
- 经典问题:如何制造一台电脑?我们会这样想:电脑一般由主机、显示屏和输入输出设备组成,主机里又包括主板、中央处理器、显卡、硬盘、内存条、散热风扇等……先制造出各个部件,再进行组装,能大大提高效率。但具体到组装或制造操作这种细节时,仍然是有步骤的,这些步骤还是以面向过程来实现
- 扮演角色:设计者
- 适用于:解决复杂的、需要协作的问题
- 编程语言代表:C++,Java等
3. 面向对象的三大特征
继承、封装、多态是面向对象的三大特征,还有一个抽象存在争论,因为万物皆可抽象,不算是特征。(以下以Java语言为例)
3.1 继承
- 关键字
- extends:子类继承父类,获得父类的全部属性和方法(父类的构造方法除外),默认继承Object类
- super:子类访问父类的属性和方法
- 父类的私有属性和方法子类不可用,final修饰的变量不可被重新赋值,final修饰的类不可被继承
3.2 封装
- 高内聚:封装内部细节,便于维护
- 低耦合:简化外部调用,便于拓展和协作
- 访问权限修饰符
修饰符 | 同一个类 | 同一个包 | 子类 | 任何地方 |
---|---|---|---|---|
private | √ | |||
default | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
3.3 多态
- 多态与属性无关,只与方法和对象类型有关
- 方法重写(override):子类重写同名方法替代父类的方法,但不是覆盖
- 返回值和异常类型:子类<=父类
- 访问权限:子类>=父类
- final修饰的方法不可被重写
- 方法重载(overload):定义多种重名的方法,根据不同的传入参数区分
- 父类(Person)的引用可指向子类(Student)的对象(此操作不可逆),然后该父类就可以自动调用子类重写的方法
- 强制类型转换只会改变引用类型(指第1行中=前的Person),实际指向对象类型(指第2行中=前的Student)不变
Person per = new Student(); //此时per的引用类型是Person,但实际指向对象类型还是Student
Student stu = (Student) per; //只将per的引用类型改为Student,使其可以对stu赋值
-
抽象方法与抽象类:关键字为abstract,抽象方法只有声明,没有方法体。抽象类就是包含抽象方法的类,继承的子类必须要实现其中的抽象方法
-
接口(interface):声明时用interface,其中的方法可实现可不实现。定义一个类实现某接口时用implements,该类里必须用重写实现接口中未实现的方法
-
反射机制(reflection):在运行中获知编译时未知目标(如泛型)的信息,如获知任意类的所有属性和方法,获知任意对象的属性和方法
方式 第一步 第二步 第三步 正常方式 引入需要的“包类”名称 通过new实例化 获得实例对象 反射方式 实例化对象 调用对象的getClass()方法 获得完整的“包类”名称 - 类的相关信息也有类:Class类、Constructor类、Field类、Method类等,可以通过调用对象的方法获得这些类:getClass()方法、getConstructor()类、getField()类、getMethod()类,获得之后便可使用
Class stuClass = Class.forname("Reflection.Student");//常用Class.forname("path")获得指定路径下的类,stuclass是被实例化的对象,其内容是Class类(“类”也能是对象)
Class cla = stuClass.getClass();//获取类
Constructor con = stuClass.getConstructor(char.class);//获取有参构造器,参数为(参数类型)
Constructor con = stuClass.getConstructor(null);//获取无参构造器
Field f = stuClass.getField('name');//获取指定属性,参数为(属性名)
Method m = stuClass.getMethod('makeFriend', String.class);//获取指定方法,参数为(方法名+形参类型)
Object obj = con.newInstance();//调用无参构造器创建对象
f.set(obj, "小对");//为obj的name属性赋值
m.invoke(obj, "小象");//调用obj的makeFriend()方法