封装、多态和继承是面向对象编程的三大特性。
封装(Encapsulation)
封装的目的是为了保证变量的安全性,使用者不必在意具体实现细节,而只是通过外部接口即可访问类的成员
如果不进行封装,类中的实例变量可以直接查看和修改,可能给整个代码带来不好的影响
因此在编写类时一般将成员变量私有化,外部类需要同getter和setter方法来查看和设置变量
继承(Inherit)
继承实际上也是为了提高代码的复用性和可扩展性,在定义不同类的时候存在一些相同属性,为了方便使用可以将这些共同属性抽象成一个父类,在定义其他子类时可以继承自该父类,减少代码的重复定义,子类可以使用父类中非私有的成员。
定义继承的格式如下:
class 子类 extends 父类 { }
可以用以下例子表示:
public class Fu {
public void show() {
System.out.println("父类中的show方法被调用");
}
public void method() {
System.out.println("父类中的method方法被调用");
}
}
public class Zi extends Fu {
@override
public void method() {
System.out.println("子类中的method方法被调用");
}
}
public class Demo {
public static void main(String[] args) {
//创建对象,调用方法
Fu f = new Fu();
f.show(); // 父类中的show方法被调用
Zi z = new Zi();
z.method(); // 子类中的show方法被调用
z.show(); // 父类中的show方法被调用
}
}
在以上代码中,Zi继承自Fu,在Zi类中重写了Fu类中的method方法,Zi类在执行method方法时执行的是重写的方法,在执行show方法时执行的是Fu类中的方法。由此可得:如果子类对父类中方法进行了重写,子类在调用该方法时执行的是重写后的方法。
除此之外,子类中还可以定义新的变量和方法
在使用继承关系时,不仅是单层继承,一般会形成一个层次关系明显的继承树,以定义狼来说,其父类可以有犬类和动物类,下图用一个稍微复杂一点的例子显示了他们之间的关系,在Java API中,大部分的继承关系都不会超过三层
继承中需要注意:
-
父类可以不知道他有哪些子类,但是子类必须明确他有哪些父类
-
子类在重写父类时,如果想在父类功能基础上增加新的功能,可以用super实现,如:
-
public void roam(){ // 父类中的方法 super.roam(); // 新增的行为 new stuff; }
-
-
不能作为继承的子类:
- 存取控制
- 使用final修饰符,防止父类方法被重写一般就是添加final修饰符
- 只有private构造方法
-
子类的参数的个数和类型要和父类完全一致,返回类型要兼容
-
子类中方法的存取权限只能改为更低,不能高于父类中方法的存取权限
多态(Polymorphism)
多态指的是同一个对象可以表现出多种形态,通俗来说就是一个对象的引用类型既可以是实际类也可以是实际类的父类。
下面一个代码实例可以直观表示
public class Animal {
public int age = 40;
public void eat() {
System.out.println("动物吃东西");
}
}
public class Cat extends Animal {
public int age = 20;
public int weight = 10;
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void playGame() {
System.out.println("猫捉迷藏");
}
}
public class AnimalDemo {
public static void main(String[] args) {
//有父类引用指向子类对象
Animal a = new Cat();
Cat c = new Cat();
System.out.println(a.age); // 40
System.out.println(((Cat) a).age); // 20
System.out.println(((Cat) a).weight); // 10
System.out.println(c.age); // 20
System.out.println(a.weight); // 10
}
}
此外,多态还可以应用到参数和返回类型中,如下代码
class Vet{
public void giveShot(Animal a){
a.makeNoise();
}
}
class PetOwner{
public void start(){
Vet v = new Ver();
Dog d = new Dog();
Hippo h = new Hippo();
v.getShot(d); //调用Dog类中的makeNoise方法
v.getShot(h); //调用Hippo类中的makeNoise方法
}
}
方法重写(override)和重载(overload)的区别
方法重载:方法重载指的是同一个类中定义多个同名方法,这些同名方法的参数个数和类型不同,返回类型和存取权限可以不同
方法重写:方法重写指的是有继承关系的子类继承父类中的方法并定义不同的方法体,子类和父类中的方法名和参数个数类型要完全一样,是一种覆盖。