在面向对象的语言中如C++和JAVA,都有一个比较重要的机制——类的继承。这里将对JAVA中的类的继承机制进行讨论。
先提一个问题:为什么要使用继承(后面再解答)。
1.首先是类继承的写法:
继承的关键字:extends
格式:
public class 类名(子类、派生类、超类) extends 类名(父类、基类) {
}
在C++中可以实现多继承,而在JAVA中存在局限,只能单继承(即一个子类只能继承一个父类)。
而多层继承是C++和JAVA中都能实现的
2.子类能继承到父类的那些内容?
子类能继承到父类的所有的属性和所有的普通方法,不能继承父类的构造方法。
注意:
1.尽管子类能继承到父类的所有的属性和所有的普通方法,但对于父类的私有属性是无法直接访问的,需要调用父类中非私有的操作来进行访问。(即对于所有的非私有(no private)操作属于显式继承(可以直接利用对象操作),而所有的私有操作属于隐式继承(间接完成))
2.在继承关系之中,如果要实例化子类对象,会默认先调用父类构造,为父类之中的属性初始化,之后再调用子类构造,为子类之中的属性初始化,即:默认情况下,子类会找到父类之中的无参构造方法。(如需调用父类的其他构造方法,需使用super)
1 class A { 2 public A() { // 父类无参构造 3 System.out.println("*************************") ; 4 } 5 } 6 class B extends A { 7 public B() { // 子类构造 8 System.out.println("#########################"); 9 } 10 } 11 public class TestDemo { 12 public static void main(String args[]) { 13 B b = new B() ; // 实例化子类对象 14 } 15 } 16 17 18 //运行结果 19 //************************* 20 //#########################
1 class A { 2 public A(String msg) { // 父类构造 3 System.out.println("*************************"); 4 } 5 } 6 7 class B extends A { 8 public B() { // 子类构造 9 super("Hello"); // 调用父类构造 10 System.out.println("#########################"); 11 } 12 } 13 14 public class TestDemo { 15 public static void main(String args[]) { 16 B b = new B(); // 实例化子类对象 17 } 18 }
3.子类方法重写
在C++中,可以在子类中写与父类具有相同函数名的函数实现覆盖。而在JAVA中,也可以通过相同的操作实现重写。但需要注意的是:private或final修饰的方法是不能被重写的。
要求:
1、在子类中可以根据需要对从基类中继承来的方法进行重写。
2、重写的方法和被重写的方法必须具有相同方法名称、参数列表和返回类型。
3、重写方法不能使用比被重写的方法更严格的访问权限。
这里还涉及到super这个关键字
当子类重写方法时,方法中需要重复父类方法的内容,可以使用super,格式:super.方法名(参数值,...)
4.转型
自动转型:
要使用自动转型,要求必须存在继承关系。
格式:
父类名 对象名A = new 子类构造方法(参数值,...);
强制转型:
如果一个对象可以被强制转型,那么肯定是在前面某个地方被自动转型过!!!
对于转型的用法,这里可以想象一个场景——老师正在教大学生学习英语;那么这位老师是否可以教初中生学习?高中生?小学生?...
按照常理肯定是可以的,但是用代码需要如何实现???
1.每个类重载一次(会不会觉得太麻烦?)
2.自动转型
考虑到大学生、初中生、高中生、小学生...都属于学生,那么可以通过一个学生的父类派生出这些类,然后在teacher类中写方法时括号内的参数就可以用student类,这样就可以通过自动转型来实现这个问题。(有没有感觉代码一下子少了很多?)
讲到这里继承的大部分的基本内容也讲完了,那么再回到上面的问题——为什么要使用继承:1.提高代码的重用性;2.提高程序的扩展性。
下面附上一串代码
1 public class Person { 2 3 public int boold; 4 private String name; 5 private int harm; 6 7 public void setName(String name) 8 { 9 this.name=name; 10 } 11 public String showName() 12 { 13 return name; 14 } 15 16 public void setHarm(int harm) 17 { 18 this.harm=harm; 19 } 20 public int showHarm() 21 { 22 return harm; 23 } 24 public void beAttack(Person per) 25 { 26 if(per.check()) 27 boold-=per.harm; 28 } 29 public boolean check() 30 { 31 if(boold<=0) 32 { 33 return false; 34 } 35 else 36 return true; 37 } 38 }
1 public class Ultraman extends Person { 2 3 public void beAttack(Person per) 4 { 5 super.beAttack(per);//super,将父类中该方法已有的内容“复制”到这 6 if(per.check()) 7 System.out.println(showName()+"受到"+per.showName()+"的攻击,减少"+per.showHarm()+"滴血,剩余血量"+boold); 8 if(!check()) 9 { 10 System.out.println(per.showName()+"胜利"); 11 } 12 } 13 14 }
1 public class Monstrous extends Person{ 2 3 public void beAttack(Person per) 4 { 5 super.beAttack(per); 6 if(per.check()) 7 System.out.println(showName()+"受到"+per.showName()+"的攻击,减少"+per.showHarm()+"滴血,剩余血量"+boold); 8 if(!check()) 9 { 10 System.out.println(per.showName()+"胜利"); 11 } 12 } 13 14 }
1 public class Manager { 2 3 public static void main(String[] args) { 4 Ultraman ult1 = new Ultraman(); 5 Ultraman ult2 = new Ultraman(); 6 Monstrous mon1 = new Monstrous(); 7 Monstrous mon2 = new Monstrous(); 8 9 ult1.setName("奥特曼A"); 10 ult1.setHarm(2); 11 ult1.boold=10; 12 ult2.setName("奥特曼B"); 13 ult2.setHarm(2); 14 ult2.boold=10; 15 16 mon1.setHarm(1); 17 mon1.setName("小怪兽A"); 18 mon1.boold=10; 19 mon2.setHarm(2); 20 mon2.setName("小怪兽B"); 21 mon2.boold=10; 22 23 while(ult1.check()&&mon1.check()) 24 { 25 ult1.beAttack(mon1); 26 mon1.beAttack(ult1); 27 if(!ult1.check()) 28 { 29 mon1.boold=10; 30 while(mon1.check()&&mon2.check()) 31 { 32 33 mon2.beAttack(mon1); 34 mon1.beAttack(mon2); 35 } 36 } 37 else if(!mon1.check()) 38 { 39 ult1.boold=10; 40 while(ult1.check()&&ult2.check()) 41 { 42 43 ult2.beAttack(ult1); 44 ult1.beAttack(ult2); 45 } 46 } 47 } 48 } 49 50 }