面向对象_继承
A.方法重写
1)概念
子类出现了和父类一模一样的方法声明
举例:需求:
定义一个手机类:手机类有打电话的功能
定义一个新手机类:有听音乐的功能,打电话的功能,是手机类的一种
分析:
如果不是跟父类一样的方法,子类中还想去使用父类的打电话功能,如何访问?
super调用父类的成员方法:默认父类成员方法
子类为什么会出现方法重写?
子类出现了一样的方法声明,有时候可能子类会有自己特有的功能,需要重写
代码:
//手机类 class Phone { public void call(String name){ System.out.println("给" + name + "打电话"); } } //新手机类 class NewPhone extends Phone { @Override //重写父类中的call()方法 public void call(Strnig name){ System.out.println("给" + name + "打电话"); System.out.println("这个手机新增了打电话的功能"); } //听音乐功能 public void music(){ System.out.println("听音乐功能..."); } } //测试类 public class Demo01 { public static void main(Strnig[] args){ //创建子类对象 NewPhone np = new NewPhone(); np.call("张三"); np.music(); } }
2)面试题
方法重载和方法重写的区别?
overload:在同一个类中,方法名相同,参数列表不同(参数个数/参数类型),与返回值无关
override:子类和父类的方法一模一样,连返回值都一样
3)方法重写的注意事项
a.如果父类的成员方法被private修饰,子类中的方法不能重写父类的私有方法
b.子类要重写父类的方法,访问权限不能更低
子类和父类方法保持一致
c.如果父类中的成员方法是静态方法,子类重写父类中的这个方法,必须也是静态
(静态方法算不上方法重写)规则:静态只能访问静态
4)猫狗案例继承版
分析:
猫:成员变量:name,age,color
构造方法
成员方法:set()/get()
特有功能:玩游戏playGame();
狗:成员变量:name,age,color
构造方法:无参/有参
成员方法:set()/get()
特有功能:看门lookDoor();
共同属性成立一个独立类
动物类:成员变量:name,age,color
构造方法
成员方法:set()/get(),show(),sleep(),eat()
代码:
动物类
//动物类 public class Animal { // 成员变量 private String name; private int age; private String color; // 构造方法 public Animal() { } public Animal(String name, int age, String color) { this.name = name; this.age = age; this.color = color; } // set/get方法 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } // show方法 public void show() { System.out.println(getName() + "---" + getAge() + "岁---" + getColor()); } // sleep方法 public void sleep() { System.out.println("困了要睡觉"); } }
猫类
//猫类 public class Cat extends Animal { // 构造方法 public Cat() { super(); } public Cat(String name, int age, String color) { super(name, age, color); } // 方法重写 @Override public void sleep() { System.out.println("猫趴着睡觉"); } // playGame() public void playGame() { System.out.println("猫玩球..."); } } 狗类
//狗类 public class Dog extends Animal { // 构造方法 public Dog() { super(); } public Dog(String name, int age, String color) { super(name, age, color); } // 方法重写 @Override public void sleep() { System.out.println("狗卧着睡觉"); } // lookDoor() public void lookDoor() { System.out.println("狗看门..."); } } 测试类
//测试类 public class Demo01 { public static void main(String[] args) { // 测试猫类 Cat c = new Cat(); c.setName("Tom"); c.setAge(5); c.setColor("蓝色"); c.show(); c.sleep(); c.playGame(); System.out.println("-----------"); // 测试狗类 Dog d = new Dog("旺财", 8, "黑色"); d.show(); d.sleep(); d.lookDoor(); } }
5)看程序写结果
//看程序写结果: /* * 子父类的初始化问题:(多次初始化) * 先让父类进行初始化,然后子类进行初始化 * * 对象初始化的问题: * 默认初始化 * 显示初始化 * 构造方法初始化! * */ class X { Y b = new Y(); X() { System.out.print("X"); } } class Y { Y() { System.out.print("Y"); } } //测试类 public class Z extends X{ Y y = new Y(); Z() { // super(); System.out.print("Z"); } public static void main(String[] args) { new Z(); } }
结果:
YXYZ
B.final关键字
1)继承的另一个特点
子类会出现和父类一样的方法声明
在上一节中:子类通过方法重写覆盖掉了父类的方法
但有时候我们不想子类去重写父类中的方法,java中提供了一个关键字:final
final:最终的,终态的!(表示:无法更改的)
2)final的用法
final可以修饰类:该类不能被继承
final可以修饰成员方法:该方法不能被重写
final可以修饰变量(成员/局部变量),这个时候变量就变成了一个常量
//final class Father{} //不能被继承 class Fu { public int num = 100; public final int num2 = 200; public void method() { int num = 20; int num2 = 50; System.err.println("show Fu"); } final public void function() { System.out.println("function Fu"); } } class Zi extends Fu { public void show() { System.out.println("show Zi"); } // 该方法在父类中被final修饰,不能被重写 // public void function() { // // } } // 测试类 public class Demo02 { public static void main(String[] args) { Zi z = new Zi(); // z.sum2 = 100; //sum2 cannot be resolved or is not a field } }
3)关于final修饰变量(基本数据类型(引用类型))的问题
final修饰基本数据类型:基本数据类型的值不能再改变,变量此时是常量
final修饰引用类型:引用类型的地址值不能发生改变,对象中对内存的值是可以改变的(考点)
class Student { int age = 10; } // 测试类 public class Demo02 { public static void main(String[] args) { int x = 10; x = 20; System.out.println(x); // x = 20 // final修饰基本数据类型 final int y = 20; // 无法为y进行赋值 // y = 10; The final local variable y cannot be assigned. System.out.println(y); Student s = new Student(); s.age = 20; System.out.println(s.age); final Student ss = new Student(); ss.age = 25; System.out.println(ss.age); // 属于新建了个对象,在堆内存中开辟了一个新的空间 // ss = new Student(); } }
4)final初始化时机的问题
final去修饰变量,这个变量是常量,只能修改一次
被final修饰变量:在调用构造方法之前,被final修饰的变量必须被使用