JAVA学习10-29——重写、super、多态性

JAVA学习10-29——重写、super、多态性,第1张

JAVA学习10-29——重写、super、多态性 方法的重写
  • 1.重写:子类继承父类以后,可以对父类中的方法进行覆盖 *** 作。
  • 2.应用:重写以后,当创建子类对象以后,通过子类对象去调用子父类中同名同参数方法时,执行的是子类重写父类的方法。
    即在程序执行时,子类的方法将覆盖父类的方法。
  • 3.重写的规定:
    方法的声明:权限修饰符 返回值类型 方法名(形参列表){
    //方法体
    }
    约定俗称:子类中的叫重写的方法,父类中的叫被重写的方法。
  • ① 子类重写的方法的方法名和形参列表必须和父类被重写的方法的方法名、形参列表相同;
  • ② 子类重写的方法使用的访问权限不能小于父类被重写的方法的访问权限,
    特殊情况: 子类不能重写父类中声明为private权限的方法;(权限太小,子类看不到,所以无所谓覆盖)
  • ③ 返回值类型:
    父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void;
    父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型可以是A类或A类的子类;
    父类被重写的方法的返回值类型如果是基本数据类型(比如:double),则子类重写的方法的返回值类型必须是相同的基本数据类型(必须是:double)。
  • ④ 子类方法抛出的异常不能大于父类被重写的方法抛出的异常;
    注意:子类与父类中同名同参数的方法必须同时声明为非static的(即为重写),或者同时声明为static的(不是重写)。因为static方法是属于类的,子类无法覆盖父类的方法

面试题:区分方法的重载与重写(有的书也叫做“覆盖”)

答:方法的重写Overriding和重载Overloading是Java多态性的不同表现。
重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。
如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。
子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被"屏蔽"了。
如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。

super关键字

super关键字的使用

  • 1.super理解为:父类的
  • 2.super可以用来调用:属性、方法、构造器
  • 3.super的使用
  • 3.1 我们可以在子类的方法或构造器中,通过"super.属性"或"super.方法"的方式,显式的调用
    父类中声明的属性或方法。但是,通常情况下,我们习惯去省略这个"super."
  • 3.2 特殊情况:当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显式的 使用"super.属性"的方式,表明调用的是父类中声明的属性。
  • 3.3 特殊情况:当子类重写了父类中的方法后,我们想在子类的方法中调用父类中被重写的方法时,必须显式的使用"super.方法"的方式,表明调用的是父类中被重写的方法。
    4.super调用构造器
  • 4.1 我们可以在子类的构造器中显式的使用"super(形参列表)"的方式,调用父类中声明的指定的构造器
  • 4.2 "super(形参列表)"的使用,必须声明在子类构造器的首行!
  • 4.3 我们在类的构造器中,针对于"this(形参列表)"或"super(形参列表)"只能二选一,不能同时出现。
  • 4.4 在构造器的首行,既没有显式的声明"this(形参列表)“或"super(形参列表)”,则默认的调用的是父类中的空参构造器。super()
  • 4.5 在类的多个构造器中,至少有一个类的构造器使用了"super(形参列表)",调用父类中的构造器。

Person类

public class Person {

	String name;
	int age;
	int id = 1003;	//身份z号
	
	public Person(){
		System.out.println("我无处不在");
	}
	
	public Person(String name){
		this.name = name;
	}
	
	public Person(String name,int age){
		this(name);
		this.age = age;
	}
	
	public void eat(){
		System.out.println("人,吃饭");
	}
	
	public void walk(){
		System.out.println("人,走路");
	}
}

Student类

public class Student extends Person{
	
	String major;
	int id = 1002;	//学号
	
	public Student(){

	}
	
	public Student(String name,int age,String major){
//		this.age = age;
//		this.name = name;
		super(name,age);
		this.major = major;
	}
	
	public Student(String major){
		this.major = major;
	}
	
	public void eat(){
		System.out.println("学生多吃有营养的食物");
	}
	
	public void Study(){
		System.out.println("学生,学习知识。");
		this.eat();
		//如果,想调用父类中被重写的,不想调用子类中的方法,可以:
		super.eat();
		super.walk();//子父类中未重写的方法,用"this."或"super."调用都可以
	}
	public void show(){
		System.out.println("name = " + this.name + ",age = " + super.age);
		System.out.println("id = " + this.id);	
		System.out.println("id = " + super.id);
	}
}

测试类

public class SuperTest {
	public static void main(String[] args) {
		
		Student s = new Student(); //我无处不在
		s.show();// name=null age =0 id=1002   id=1001
		
		s.Study(); //学生,学习知识 学生多吃有营养的食物  人,吃饭 人,走路
		
		Student s1 = new Student("Ton",21,"IT" );
		s1.show();  //name=Tom age =21 id=1002   id=1001
		
		System.out.println("***********************");
		Student s2 = new Student();//我无处不在
		
	}
}
多态性
  • 1.理解多态性:可以理解为一个事物的多种态性。

  • 2.何为多态性:
    对象的多态性:父类的引用指向子类的对象(或子类的对象赋值给父类的引用)

  • 3.多态的使用:虚拟方法调用
    有了对象多态性以后,我们在编译期,只能调用父类声明的方法,但在执行期实际执行的是子类重写父类的方法
    简称:编译时,看左边;运行时,看右边。
    若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism)
    多态情况下,
    “看左边”:看的是父类的引用(父类中不具备子类特有的方法)
    “看右边”:看的是子类的对象(实际运行的是子类重写父类的方法)

  • 4.多态性的使用前提:
    ① 类的继承关系
    ② 方法的重写

  • 5.对象的多态性:只适用于方法,不适用于属性(编译和运行都看左边)

Person类

public class Person {
	String name;
	int age;
	int id=1001;
	
	public void eat(){
		System.out.println("人,吃饭");
	}
	
	public void walk(){
		System.out.println("人,走路");
	}
	
}

Man类

public class Man extends Person{
	
	boolean isSmoking;
	int id=1002;
	public void earnMoney(){
		System.out.println("男人负责工作养家");
	}
	
	public void eat() {
		System.out.println("男人多吃肉,长肌肉");
	}
	
	public void walk() {
		System.out.println("男人霸气的走路");
	}
}

测试类

public class PersonTest {
	public static void main(String[] args) {
		
	Person p1 = new Person();
	p1.eat();
	Man man = new Man();
	man.eat();
	man.age = 25;
	man.earnMoney();
	
	//************************************
	//对象的多态性,父类的引用指向子类的对象
	Person p2 = new Man();
	//多态的使用:当调用子父类同名同参数方法时,实际调用的是子类重写父类的方法---虚拟方法调用
	p2.eat();//男人多吃肉,长肌肉
	p2.walk();//男人霸气的走路
	
System.out.println(p2.id);//1001
	
	}
}

多态性应用举例

public class AnimalTest {
	
	public static void main(String[] args) {
		AnimalTest test = new AnimalTest();
		test.func(new Dog());//狗吃骨头 汪汪汪
		
		test.func(new Cat());//猫吃鱼 喵喵喵
	}

	public void func(Animal animal){	//Animal animal = new Dog();
		animal.eat();
		animal.shout();
	}
	
	//如果没有多态性,就会写很多如下的方法,去调用
	public void func(Dog dog){
		dog.eat();
		dog.shout();
	}
	
	public void func(Cat cat){
		cat.eat();
		cat.shout();
	}
}

class Animal{
	
	public void eat(){
		System.out.println("动物,进食");
	}
	
	public void shout(){
		System.out.println("动物:叫");
	}
}

class Dog extends Animal{
	public void eat(){
		System.out.println("狗吃骨头");
	}
	
	public void shout() {
		System.out.println("汪!汪!汪!");
	}
}

class Cat extends Animal{
	public void eat(){
		System.out.println("猫吃鱼");
	}
	
	public void shout() {
		System.out.println("喵!喵!喵!");
	}
}

方法的重载和重写

  • 从编译和运行的角度看:
    重载,是指允许存在多个同名方法,而这些方法的参数不同。 编译器根据方法不同的参数表,对同名方法的名称做修饰。对于编译器而言,这些同名方法就成了不同的方法。它们的调用地址在编译期就绑定了。Java的重载是可以包括父类和子类的, 即子类可以重载父类的同名不同参数的方法。所以:对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为“早绑定”或“静态绑定”;
    而对于多态,只有等到方法调用的那一刻,解释运行器才会确定所要调用的具体方法,这称为“晚绑定”或“动态绑定”。

  • 引用一句Bruce Eckel的话:“不要犯傻,如果它不是晚绑定,它就不是多态。”

  • 面试题:多态是编译时行为还是运行时行为?
    证明如下:

import java.util.Random;
class Animal  {
 
	protected void eat() {
		System.out.println("animal eat food");
	}
}

class Cat  extends Animal  {
 
	protected void eat() {
		System.out.println("cat eat fish");
	}
}

class Dog  extends Animal  {
 
	public void eat() {
		System.out.println("Dog eat bone");

	}

}

class Sheep  extends Animal  {
 
	public void eat() {
		System.out.println("Sheep eat grass");

	}
 
}

public class InterviewTest {

	public static Animal  getInstance(int key) {
		switch (key) {
		case 0:
			return new Cat ();
		case 1:
			return new Dog ();
		default:
			return new Sheep ();
		}

	}

	public static void main(String[] args) {
		int key = new Random().nextInt(3);

		System.out.println(key);

		Animal  animal = getInstance(key);
		
		animal.eat();
		 
	}

}

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/4829175.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-11-10
下一篇2022-11-10

发表评论

登录后才能评论

评论列表(0条)

    保存