final
子类继承父类的时候,有的时候不需要让子类重写父类的方法
Java提供了一个关键字:
final :状态修饰符 (终态的,无法更改的)
fianl可以修饰变量
修饰成员方法
修饰类
可以修饰类,该类不能被继承
可以修饰成员变量:此时变量是一个常量!(自定义常量)
可以修饰成员方法:该方法不能重写
class Father{
public int num = 100 ;
//num2此时已经常量
public final int num2 = 50 ; //num2已经被赋值了,不能再次赋值!
//此时父类的成员方法已经被final修饰了
public final void method(){
System.out.println("method father") ;
}
//父类的方法为静态方法
public static void function(){
System.out.println("function father") ;
}
}
//子类
class Son extends Father{
public void show(){
System.out.println(num) ;//100
System.out.println(num2) ;//50
}
/*
public void method(){ //Son中的method()无法覆盖Father中的method()
System.out.println("method son") ;
}
*/
public static void function(){
System.out.println("function son") ;
}
}
//测试类
class FinalDemo2{
public static void main(String[] args){
//创建子类对象
Son s = new Son() ;
s.show();
//s.num2 = 100;//无法为最终变量num2分配值
System.out.println(s.num2) ;
s.method();
s.function() ;
}
}
多态
定义:同一个对象,在不同时刻体现出来的不同状态。
多态的前提:
1)要有继承关系或实现关系(接口);
2)要有方法重写;
3)要有父类或者父接口引用指向子类`Fu f= new Zi();
注意:形参实参形式的(形参父类实参子类)。
多态的分类:
具体类多态
抽象类多态(常用)
接口多态(常用)
多态中成员访问特点
如,Fu f= new Zi();//左父类右子类
重点:成员方法,运行时,结果为子类重写的成员方法的结果。
成员变量:编译看左边,运行看左边。
构造方法:创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。
成员方法:编译看左边,运行看右边。(方法重写的意义)
静态方法:编译看左边,运行看左边。静态和类相关,算不上重写,所以访问还是左边的。
多态的好处
提高了代码的维护性(继承保证);提高了代码的扩展性。
原代码,不易扩展:
class Animal{
public void eat(){
System.out.println("eat");
}
public void sleep(){
System.out.println("sleep");
}
}
//猫类
class Cat extends Animal{
public void eat(){
System.out.println("狗吃肉");
}
public void sleep(){
System.out.println("狗坐着睡");
}
}
//狗类
class Dog extends Animal{
public void eat(){
System.out.println("猫吃鱼");
}
public void sleep(){
System.out.println("猫趴着睡");
}
}
//添加猪类
class Pig extends Animal{ //----------note:老忘记写extends!!!!!!!!!!
public void eat(){
System.out.println("猪吃白菜");
}
public void sleep(){
System.out.println("猪躺着睡");
}
}
//针对动物操作的工具类
class AnimalTool{
private AnimalTool(){}//最好把工具类的构造方法私有,防止别人创建该类的对象。该类是工具类。
/*-------------改动-----------------------*/
//注意:形参是Animal a,用动物接收。 到时候左边是 Fu f, 右边是Zi z, Fu f= Zi z
public static void feedAnimal(Animal a){ //工具类,方法就写成static的,然后直接在测试类:工具类名.方法 使用。
a.eat(); //成员方法:运行看右边:各子类的。( 不然干嘛方法重写)
a.sleep();
}
}
/*测试类
测试类里面不放其他东西(如,定义其他方法)!只能是建对象,调方法。
所以新定义了个操作动物的工具类去放feedCat(),feedDog()方法。
*/
class DuotaiTest2{
public static void main(String[] args){
//我喜欢猫,我养3只猫
Cat c= new Cat();
Cat c2= new Cat();
Cat c3= new Cat();
AnimalTool.feedAnimal(c);
AnimalTool.feedAnimal(c2);
AnimalTool.feedAnimal(c3);
System.out.println("---------------");
//我喜欢狗,我养3只狗
Dog d= new Dog();
Dog d2= new Dog();
Dog d3= new Dog();
AnimalTool.feedAnimal(d);
AnimalTool.feedAnimal(d2);
AnimalTool.feedAnimal(d3);
System.out.println("---------------");
//我喜欢宠物猪
//需要定义一个猪类,它继承自动物类,提供两个方法。且在工具类里添加方法。
//我喜欢宠物兔、老虎、狼.....
//若按上述添加猪的办法做,定义类,继承类,提供方法都是必须要的。
//但是在工具类里面改过来改过去,不好。能否做到不改?
//能。
//猫、狗、猪...都是动物,feedAnimal(Animal a)参数接收动物
Pig p= new Pig();
AnimalTool.feedAnimal(p);
}
}
多态的弊端是什么?以及如何解决弊端问题?
父类引用指向子类对象(向上转型),无法访问子类的特有功能!
1)直接在测试的时候,子类去创建自己的对象
Son s = new Son()
可以访问,但是从内存角度考虑,重新在堆内存中开辟空间,耗费空间的内存!
2)如果能够类似于这种方式:父类引用指向子类对象,访问的是父类,如果能够将父类的引用转换为子类引用是可以的,
将父类的引用强制转换为子类的引用 :向下转型
Zi zi = (Zi)f;