面向对象_继承

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修饰的变量必须被使用