目录
一、OOP理念
面向对象编程(Object-Oriented Programming,OOP)是当今主流的程序设计思想,在OOP中,不必关心对象的具体实现,只需满足需求即可。
以造汽车为例,面向过程:需要考虑各种实现,如将外胎、内胎、垫带按照相应规则组成在一起,置入车架底部,将方向盘外套套入盘中并通过转轴装入固定位置等;而面向对象:只需要考虑需求,如轮胎、方向盘、发动机、四周玻璃,至于怎么安装配置具体实现都不必关心。
以开汽车为例,面向过程:打火,踩离合,挂挡,加油,松离合等各种细节实现;而面向对象:司机、汽车、目的地即可,具体的开车细节隐藏在了汽车这个对象中。
OOP理念更加内聚,强调高内聚、低耦合,先抽象模型,定义共性,满足大体需求后,再使用面向过程的思想解决具体问题。
二、类与对象
类是构造对象的模板或蓝图。以制作甜甜圈为例,面粉、白砂糖、奶油和鸡蛋是基本材料(属性),配料、搅拌、发酵、油炸是制作过程(方法),将基本材料、制作过程等抽取出来作为甜甜圈类,每个成型可食用的甜甜圈就是一个对象。即常用术语,类是对象的抽象,对象是类的具体化实例。
2.1、类的定义
推荐首先定义成员变量,然后定义方法。定义方法时建议按照,公有方法---->保护方法---->私有方法---->getter/setter方法的顺序去创建。公有方法是类调用者和维护者最关心的方法,因此最好首先展示;保护方法虽然只被子类关心,但也可能是模板设计模式下的核心方法,重要性紧随其后;私有方法对外部来说是一个黑盒实现,一般不需要被特别关注;最后是getter/setter方法,虽然他们也是公有方法,但是因为承载的信息价值比较低,一般不包含业务逻辑,所以位于最后。
2.2、隐式参数(this/super)
对象实例化时,至少有一条从本类出发抵达Object的通路,而打通这条路的角色就是this和super。任何类在创建之初,都有一个默认的构造方法,它是super()的一条通路。如果子类指定调用父类的某个构造方法,super就会向上不断溯源;如果没有指定,则默认调用super();如果父类没有提供默认的构造方法,子类在继承时就会出现编译错误。如果父类坚持不提供有参构造方法,必须在子类的无参构造中使用super方式调用父类的有参构造方法。
class Animal{
public Animal(String name) {
}
}
class Cat extends Animal {
public Cat() {
super("猫");
}
}
如果this和super指构造方法,则必须位于方法体第一行。即在一个构造方法中,this和super只能出现一个,且只能出现一次。否则在实例化对象的时候,可能因为子类调用父类多个构造方法而出现混乱。
因为this和super都在对象实例化阶段调用,所以不能再静态方法和静态代码块中使用this和super关键词。
this与super异同点总结如下图。
2.3、访问权限控制
在定义类时,需要谨慎考虑属性、方法、内部类的访问权限,过于宽泛的访问范围不利于模块间解耦及未来代码维护工作。试想,在代码重构时,private方法过于陈旧,我们可以直接进行删除,而无后顾之忧。对于public方法,必须谨慎地检查是否被调用。
2.4、类关系
在类图中,有形状的图形符号一律放在权利强的这一侧。
2.5、内部类
任何一个类都可以在内部定义另外一个类,前者为外部类,后者为内部类。内部类本身就是类的一个属性,与其他属性定义方式一样。如private static class Inner{},和属性定义一样,由访问控制符、是否静态、类型、变量名组成。内部类可以是静态或者非静态的,它可以出现在属性定义、方法体和表达式中,甚至可以匿名出现。具体分为如下四种。
①静态内部类☆,如:static class StaticInnerClass{};
②成员内部类,如:private class InstanceInnerClass{};
③局部内部类,定义在方法或者表达式内部;
④匿名内部类☆,如:(new Thread(){}).start();
如下是最精简的4中内部类定义方式。
public class OuterClass {
// 成员内部类
private class InstanceInnerClass {};
// 静态内部类
static class StaticInnerClass {};
public void oneMethod() {
// 匿名内部类
(new Thread() {}).start();
// 局部内部类
class MethodClass {};
}
}
匿名内部类和静态内部类是比较常用的方式。匿名内部类可以减少代码量,静态内部类是最常用的内部表现形式,外部可以使用OuterClass.StaticInnerClass直接访问。定义静态内部类好处:作用域不会扩散到包外、可以通过"外部类.内部类"的方式直接访问、内部类可以访问外部类中所有的静态属性和方法。