Java继承(方法的重写和多态)

方法的重写

什么是方法的重写:

  • 当父类的功能无法满足子类的需求时,在子类中写一个与父类出了同名的函数,这个我们就称作为方法的重写。

方法重写的注意事项:

  1. 方法重写时, 方法名与形参列表必须一致。
public class One {
	public static void main(String[] arg) {
		Student one = new Student();
		one.Run();
	}
}

class Person{
	public void Run() {
		System.out.println("我能跑");
	}
}

class Student extends Person{
	public void Run() {
		System.out.println("我能跑的很快");
	}
}

运行结果:我能跑的很快
  1. 方法重写时,子类的权限修饰符必须要大于或者等于父类的权限修饰符。

  2. 返回值类型:
    如果父类被重写的方法没有返回值类型或者返回值类型为基本数据类型,则要求子类重写的方法的返回值类型和父类被重写方法的返回值类型相同;
    如果父类被重写的方法返回值类型为引用数据类型,则要求子类重写的方法的返回值类型和父类被重写方法的返回值类型相同或是其子类。

public class One {
	public static void main(String[] arg) {
		Student one = new Student();
		one.Run();
	}
}

class Person{
	public Object Run() {
		System.out.println("我能跑");
		return "";
	}
}

class Student extends Person{
	public String Run() { //String类是Object类的子类,所以不会报错
		System.out.println("我能跑的很快");
		return "";
	}
}
  1. 父类中被final关键字修饰的方法可以被子类继承,但却不能被子类重写
    Java继承(方法的重写和多态)_第1张图片
  2. 父类私有方法,子类看不到,因此父类私有方法的重写也就无从谈起。
  3. 静态方法不能够被重写。
public class One {
	public static void main(String[] arg) {
		Student one = new Person();
		one.Eat();//我能吃饭,执行的是父类中的静态方法,没有达到重写的目的
	}
}
class Person{
	public static void Eat() {
		System.out.println("我能吃饭");
	}
}
class Student extends Person{
	//加上@Override报错:The method Eat() of type Student must override or implement a supertype method
	public static void Eat() {
		//静态方法只能重写静态方法
		System.out.println("我能吃饭很快");
	}
}
  • @Override注解可以判断当前方法是否重写了父类的某个方法,如果在方法上加上该注解没有出错,则说明重写了父类方法,否则没有重写父类方法。
class Student extends Person{
	@Override //添加注解
	public void Run() {
		System.out.println("我能跑的很快");
	}
}

super关键字

  1. super关键字可以调用父类的成员变量( super.属性)和方法(super.父类方法([参数列表]))。
  2. 子类构造方法中可以使用super关键字调用父类的构造方法:super([参数列表])。
  3. super 不能用于静态方法或静态代码块中。

final关键字

  • final关键字可以用来修饰类、方法和变量。
  • final修饰的类不能被继承。
  • final修饰的方法不能被重写。
  • final修饰的变量是常量,不允许二次赋值。

多态

什么是多态:

  • 父类类型的变量指向子类创建的对象,使用该变量调用父类中一个被子类重写的方法,则父类中的方法呈现出不同的行为特征,这就是多态。
  • Java引用变量有两种类型,分别是编译时类型和运行时类型:编译时类型由声明该变量时使用的类型决定;运行时类型由实际赋给该变量的对象。如果编译时类型和运行时类型不一致,就可能出现所谓多态。
public class One {
	public static void main(String[] arg) {
		Person one = new Student();
		one.Run();
		//编译时调用的为父类中的Run()方法,运行时调用的为子类中的Run()方法,此为多态(即对象在不同时刻表现出来的状态)。
	}
}
class Person{
	public void Run() {
		System.out.println("我能跑");
	}
}
class Student extends Person{
	@Override //添加注解
	public void Run() {
		System.out.println("我能跑的很快");
	}
}

多态的前提:

  1. 要有继承或者实现关系。
  2. 要有方法的重写。
  3. 要有父类引用指向子类对象。

注意:

  1. 子类实例化的对象赋值给父类声明变量,则该对象称为上转型对象,这个过程称为对象上转型,对应于数据类型转换中的自动类型转换:
public class One {
	public static void main(String[] arg) {
		Person one = new Student(); 
		//one称为上转型对象
	}
}
  1. 上转对象调用父类方法,如果该方法已被子类重写,则表现子类重写后的行为特征,否则表现父类的行为特征。
public class One {
	public static void main(String[] arg) {
		Person one = new Student();
		one.Run(); //该方法已被子类重写,则调用子类重写后的方法
		one.Eat(); //该方法没有被子类重写,调用父类的方法
	}
}
class Person{
	public void Run() {
		System.out.println("我能跑");
	}
	
	public void Eat() {
		System.out.println("我能吃");
	}
	
}
class Student extends Person{
	@Override //添加注解
	public void Run() {
		System.out.println("我能跑的很快");
	}
}
运行结果:
我能跑的很快
我能吃
  1. 使用上转型对象调用成员变量,无论该成员变量是否已经被子类覆盖,使用的都是父类中的成员变量:
    即:属性没有重写的说法。原因:因为属性是需要封装的,所以重写属性是无意义的。
public class One {
	public static void main(String[] arg) {
		Person one = new Student();
		System.out.println(one.name); //调用的为父类的成员变量
	}
}
class Person{
	String name = "父类";
}
class Student extends Person{
	String name = "子类";
}
运行结果:父类
  1. 上转型对象不能操作子类新增的成员变量,不能调用子类新增的方法。
    Java继承(方法的重写和多态)_第2张图片

  2. 可以将上转型对象再强制转换为创建该对象的子类类型的对象,即将上转型对象还原为子类对象(对应于数据类型转换中的强制类型转换)。
    还原后的对象又具备了子类所有属性和功能,即可以操作子类中继承或新增的成员变量,可以调用子类中继承或新增的方法。

public class One {
	public static void main(String[] arg) {
		Person one = new Student(); //上转型的对象
		Student two = (Student)one; //下转型的对象
//		System.out.println(one.name);调用时报错
		System.out.println(two.name); //下转型的对象可以调用子类新增的属性
	}
}
class Person{
}
class Student extends Person{
	String name = "学生";
}

注意:不可以将父类创建的对象通过强制类型转换赋值给子类声明的变量。

Java继承(方法的重写和多态)_第3张图片

你可能感兴趣的:(Java基础)