高内聚和低耦合
面向对象的最终目的是要构建强健、安全、高效的项目,也就是要实现项目的高内聚和低耦合:
访问权限修饰符应封装的隐藏细节的理念,java提供了访问权限修饰符来控制调用者的访问权限,详情如下:
一般情况下,类的字段都使用private修饰;封装了实现细节的方法,一般也使用private修饰,因为不希望调用者直接访问其实现细节,而是要通过公开的public方法间接调用。
// 公开给调用者访问的public方法
public void doWork(){
methodA();
methodB();
methodC();
}
// 三个方法分别封装了部分实现细节
private methodA(){}
private methodB(){}
private methodC(){}
很少会使用(缺省),即使要使用,也仅仅是暴露给同包中的其他类访问;protected很多时候出现在继承关系中,父类只希望被子类访问的字段和方法时;
从面向对象的角度上说,继承是一种从一般到特殊的关系,是一种“is a”的关系,即子类是对父类的拓展,是一种特殊的父类,比如:狗是动物的一种特殊情况,狗属于动物;在这个例子中,动物是父类,狗是子类,狗继承了动物的特征和行为,并在动物的特征和行为的基础之上拓展自己的特征和行为,构成了狗这种特殊的动物。
所以可以基于父类并对其加以拓展,产生新的子类定义,这就是继承;子类可以通过继承获得父类原有的字段和方法,也可以增加父类所没有的字段和方法,更是可以覆写父类中的允许被子类覆盖的字段或者方法。
在Java中使用”extends”关键字来表示子类和父类之间的继承关系;在Java中,类之间的继承关系只允许单继承,不允许多继承,一个类只能有一个直接父类。语法格式如下:
public class 子类类名 extends 父类类名
{
// 编写自己特有的状态和行为
}
也就是说一个类只能有一个直接的父类,不能出现类A同时继承于类B和类C。即便不允许多继承,但是多重继承是被允许的。以下是一个多重继承的例子:动物有胎生动物和卵生动物之分,胎生动物有老虎,老虎又分华南虎,东北虎,孟加拉虎等。在继承体系中可以这样来表示:
华南虎——》老虎——》胎生动物——》动物
最终,华南虎通过多重继承获得了老虎、胎生动物、动物的特征和行为。
(根据访问修饰符来判断):
方法重写(Override):从父类继承的方法(行为)不符合子类的功能需求,那此时子类就需要重新实现父类的方法,并重写方法体,以实现子类需求。方法重写的原则:一同、两小、一大
// 父类
class SuperClass {
protected void work() throws Exception {}
}
// 子类
class SubClass extends SuperClass {
@Override
protected void work() throws NullPointerException, NumberFormatException {}
}
在重写方法父类方法时,使用@Override注解修饰方法,若是重写错误,就会报编译错误,是一大开发利器;这里需要注意的是只有方法会被重写,字段则没有重写一说。
方法重载(Overload): 在同一个类中,方法名字相同,但是因方法参数列表不同而又不同的实现,这样的机制称为方法重载,其实现原则是:两同、一不同,返回值并不计入其中。
protected void work() {}
protected int work(String str) {
return 0;
}
方法重载(Overload)和方法重写(Override)两者只是名字上比较接近,其本身并没有关系。
this关键字表示当前对象,当前对象就是this所在的这个对象。this主要存在于两个位置:
当一个对象创建之后,JVM会为对象分配一个引用该对象自身的引用:this。this的使用是为了:
在对象中this表示当前对象,而super则表示当前对象的父类对象。在子类初始化过程中会创建子类对象,但在创建子类对象之前,会先创建父类对象;也就是说调用子类构造器之前,在子类构造器中会先调用父类的构造器,如果没有显式的调用父类构造器,那么默认情况下会隐式的调用父类无参数构造器。
super关键字用于显式调用父类方法、构造器和字段;可以使用super解决子类隐藏了父类的字段情况;
class SuperClass {
public SuperClass() {}
}
class SubClass extends SuperClass {
public SubClass() {
super(); // 调用父类构造器
}
}
上文中提到了隐藏的概念,继承中的隐藏表示会忽略一些特征和方法,比如静态字段和静态方法:
无论是this,还是super,都不能和static一起使用。
在Java中除去Object类之外的每一个类都有一个直接或间接的父类:Object类。也就是说除去Object类之外的类都是Object类的直接子类或间接子类。比如:
class Person {}
class Student extends Person{}
此时Student类的直接父类是Person,Person类的直接父类是Object类,Object类是Student类的间接父类。
Object类是Java的基类,Java中的类都是Object的直接或者间接的子类,Object本身是指对象的意思, 它是所有的对象都具有的共同的行为的抽象类,其他类都会直接或者间接继承于Object类,然后也就拥有了Object类中的方法。
class SuperClass {}
// 等价于
class SuperClass extends Object {}
通过上文,讲清楚了继承关系,继承关系是一种”is a”(是一种)的关系,也就是说子类是父类的一种特殊情况;既然子类是一种特殊的父类,我们是否可以认为子类对象就是父类类型的对象。考虑以下的代码:
Animal d = new Dog(); //创建一只狗对象,类型是动物
Animal c = new Cat(); //创建一只猫对象,类型是动物
这个时候,多态就产生了。我们以下面的代码为例,详细解释什么是多态:
Animal a = new Dog();
在上例中,对象a具有两种类型:
编译类型必须是运行类型的父类或与之相同,当编译类型和运行类型不同的时候,多态就产生了。所谓多态是指对象具有多种形态,对象可以存在不同的形式:
Animal a = null;
a = new Dog(); //a此时表示Dog类型的形态
a = new Cat(); //a此时表示Cat类型的形态
多态可以是类和类之间的继承关系,也可以是接口和实现类间的实现关系,一般情况下指的都是接口和实现类间的实现关系。多态的特点:把子类对象赋给父类类型的变量,在运行时期会表现出具体的子类特征,比如父类类型的变量调用子类的方法。
多态的好处:通过一个例子呈现。
需求:给饲养员提供一个喂养动物的方法,用于喂养动物。
1.基本数据类型转换:大和小表示的是可存储的容量范围。
2.自动类型转换:把小类型的数据赋给大类型的变量:
3.强制类型转换:把大类型的数据赋给小类型的变量。
short s = (short) i ; // short是2个字节
4.引用类型的转换: 引用类型的大和小,指的是父类和子类的关系。
5.自动类型转换:把子类对象赋给父类变量(多态)。
Animal a = new Dog();
Object obj = new Dog();
6.强制类型转换:把父类类型对象赋给子类类型变量(对象的真实类型是子类类型)。
Animal a = new Dog();
Dog d = (Dog)a;
instanceof 运算符:判断该对象是否是某一个类的实例。语法格式如下:
boolean b = 对象A instanceof 类B; // 判断 A对象是否是 B类的实例,如果是,返回true.
在继承关系中,子类可以继承到父类中部分的成员,那么此时子类是可以修改到父类的信息的,此时的继承关系破坏了封装,让子类拥有了本不该具有的功能。那么这时可以使用”包含关系”(has a)的组合关系。
可以这么理解组合关系:把另一个类当作属性来获取其特征和行为。比如:需求是:我想拥有天子的权力;
思考:如果A类想要得到B的功能行为,如若A类是B类的一种特殊情况,就应该采用继承来实现,否则使用组合方式。
class Cat {
public void eatMouse() {
System.out.println("猫吃老鼠");
}
}
class XiaoMing {
// 把cat类当作属性引入 private Cat cat;
public XiaoMing() {
cat = new Cat();
}
public void killMouse() {
cat.eatMouse():
}
}
完结。老夫虽不正经,但老夫一身的才华