Java 继承与多态

Java 继承与多态

1.父类与子类
子类从它的父类中继承可访问的数据域和方法,还可以添加新数据域和新方法。
父类中的私有数据域在该类之外是不可访问的。因此,不能在子类中直接使用。但是,如果父类中定义了公共的访问器 / 修改器,那么可以通过这些公共的访问器 / 修改器来访问和修改它们。
2.super关键字

语句 super() 调用父类的无参构造方法,而语句 super (arguments) 调用与参数匹配的父类的构造方法。语句 super() 和 super (arguments) 必须出现在类构造方法的第一行,这是显式调用父类构造方法的唯一方式。


构造方法可以调用重载的构造方法或父类的构造方法。如果它们都没有被显式地调用,编译器就会自动地将 super() 作为构造方法的第一条语句。

public class Faculty extends Employee {
public static void main(String[]args){
	new Faculty();
	}
	public Faculty() {
		System.out.println("(4) Performs Faculty's tasks");
		}
}

class Employee extends Person {
	public Employee(){
		this("(2)Invoke Employee's overloaded constructor");
		System.out.println("(3)Performs Employee's tasks ");
}

	public Employee(String s){
		System.out.println(s);
	}
}

 class Person {
 	public Person() {
 		System.out.println("(l)Performs Person's tasks");
	}	
}
/*  输出
(1) Performs Person's tasks
(2) Invoke Employee' s overloaded constructor
(3) Performs Employee's tasks
(4) Performs Faculty's tasks
*/

关键字 super 不仅可以引用父类的构造方法,也可以引用父类的方法。所用语法如下:
super.方法名(参数);
3.方法重写
·仅当实例方法是可访问时,它才能被覆盖。因为私有方法在它的类本身以外是不能访问的,所以它不能被覆盖。如果子类中定义的方法在父类中是私有的,那么这两个方法完全没有关系。
·与实例方法一样,静态方法也能被继承。但是,静态方法不能被覆盖。如果父类中定义的静态方法在子类中被重新定义,那么在父类中定义的静态方法将被隐藏。可以使用语法:父类名 .静态方法名( SuperClassName.staticMethodName) 调用隐藏的静态方法。

方法重写与方法重载不同 要主要区分:
• 方法重写发生在通过继承而相关的不同类中;方法重载可以发生在同一个类中,也
可以发生在由于继承而相关的不同类中。
•方法重写具有同样的签名和返回值类型;方法重载具有同样的名字,但是不同的参
数列表。
4.多态
(1)子类重写父类的方法。使子类具有不同的方法实现。

(2)把父类类型作为参数类型,该父类及其子类对象作为参数转入。

(3)运行时,根据实际创建的对象类型动态决定使用那个方法。

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。


5.动态绑定
所谓动态绑定,通俗的是指,对象在调用方法的时候能够自己判断该调用谁的方法。所以动态绑定一般发生在继承、方法重载时。
那么发生方法重载时,编译器如何确定调用的方法呢,例如,调用c.f(arg)时,首先需要将c声明为B类的对象,此时,如果在B类中,存在多个f方法,只是f的参数类型不同,调用f(int)或者f(String)时。编译器会注意列举B类中所有名为f的方法以及B类超类中的访问权限为public的名为f的方法。如果存在与c.f(arg)中arg类型相匹配的方法,那么就调用这个方法。由此,调用哪个方法隐式参数的实际类型。这个过程就是一个动态绑定的过程。

package chapeter04;
 
class Test
{
	public Test() { }
	
	public void setName(String n)
	{
		this.name=n;
		System.out.println("在父类中");
	}
	
	public String getName()
	{
		return this.name;
	}
	
	private String name;
}
 
public class Sample4_12 extends Test
{
	public void setArea(String a)
	{
		this.area=a;
	}
 
	public String getArea()
	{
		return this.area;
	}
	
	public static void main(String[] args) 
	{
		// TODO Auto-generated method stub
		Sample4_12 child = new Sample4_12();
		
		Test test []=new Test[2];
		test[0]=child;
		test[0].setName("silence");
		test[1]=new Test();
	}
	
	private String area;
 
}
/*
	运行结果:
	在父类中
*/

上面的例子执行过程如下:
查看test[0]声明类型,即Sample4_12 类,然后获得方法名 setName ,接着把PolymorphicTest 类中的所有名为setName的public方法列举出来。若没有名为setName的方法,则调用失败,否则转换到2。
根据调用方法的参数类型来对上一步列出来的所有方法进行匹配,直到找到一个匹配的转到3,否则匹配失败。
若test[0]所指向(refer to)的对象的类型为其一个子类,则需要查看子类有没有覆盖该方法,若有,则执行子类中的方法。
如果这个方法是private、static、final类型的,就不用进行动态绑定了,因为编译器可以很准确的知道要调用那个方法。且查询匹配方法时,是按照继承树逐级向上查找的,直到找到第一个匹配的方法为止。
但是由于Java中允许类型转换,所以寻找一个合适的方法是个复杂的过程,如果编译器没有找到合适的方法,或者发现类型转换后有多个方法与之匹配,则编译器会报错。
6.incetanceof
instanceof是Java中的二元运算符,左边是对象,右边是类;当对象是右边类或子类所创建对象时,返回true;否则,返回false。

1.类的实例包含本身的实例,以及所有直接或间接子类的实例
2.instanceof左边显式声明的类型与右边操作元必须是同种类或存在继承关系,也就是说需要位于同一个继承树,否则会编译错误。


下面是一个完整的样例

package sample;

public class person{
	public String name;
	public int age;
	public person(String a,int b) {
		name = a;
		age = b;
	}
	public void eat() {
		System.out.println(this.name+"吃");
	}
	public void sleep() {
		System.out.println(this.name+"睡");
	}
	public void work() {
		System.out.println(this.name+"工作");
	}
	public void show() {
		this.eat();
		this.sleep();
		this.work();
	}
}
package sample;

public class master extends person{
	public master(String a,int b) {
		super(a,b);
	}
	public void work() {
		System.out.println(this.name+"练功");
	}
}


package sample;

public class student extends person{
	public student(String a,int b) {
		super(a,b);
	}
	public void work() {
		System.out.println(this.name+"学习");
	}
}

package sample;

public class test {
	public static void main(String[] args) {
	      show(new student("田所浩二",24));  // 以 学生 对象调用 show 方法
	      show(new master("马保国",69));  // 以 大师 对象调用 show 方法
	                
	      person a = new student("田所浩二",24);  // 向上转型  
	      a.eat();               // 调用的是 学生 的 eat
	      student c = (student)a;        // 向下转型  
	      c.work();        // 调用的是 学生 的 work
	  }  
	            
	    public static void show(person a)  {
	        // 类型判断
	        if (a instanceof student)  {  // 学生做的事情 
	            student c = (student)a;  
	            c.show();  
	        } else if (a instanceof master) { // 大师做的事情 
	            master c = (master)a;  
	            c.show();  
	        }  
	    }  
	
	 
}

输出结果为:
田所浩二吃
田所浩二睡
田所浩二学习
马保国吃
马保国睡
马保国练功
田所浩二吃
田所浩二学习

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值