类的继承的总结
类继承是为了提高代码的重用性!
一、Java继承的语法格式:
继承的
关键字:extends
格式:
public
class 类名(子类、超类、派生类) extends 类名(父类、基类) {
}
注意:Java的继承是单继承(一个子类只能继承一个父类),表示extends后边只能加一个类名。
二、子类能继承到什么?又能使用什么?
1.子类能继承到父类所有的属性和方法。
2.子类能调用的方法:
1).当子类和父类同包:默认的、受保护的、公有的属性和方法能被子类的对象和子类{}中调用。
2).当子类和父类不同包:子类对象能调用的只有:公有的属性和方法
子类的{}中能调用的属性和方法有:公有的、受保护的
3.属性和方法是否能够被调用取决于Java的访问修饰符。
private 不论子类和父类是否同包,都不能被子类的对象和子类{}直接调用。
默认的 在子类和父类同包的情况下,能被子类的对象和子类{}调用。
protected 在子类和父类同包的情况下能被子类的对象和子类{}中调用,在子类和父类不同包的情况下能被子类的{}调用。
public 不论子类和父类是否同包,都能够被子类的对象和子类{}调用。
三、方法重写
1.实现方法重写的条件:
1).必须要存在继承关系。
2).返回值数据类型、方法名、参数个数、参数类型和参数顺序必须要和父类方法的完全一致。
3).子类重写方法时,方法的访问修饰符可以大于或者等于父类方法的访问修饰符。
exp: 默认-->protected-->public
2.重写后的方法是如何调用的呢?
1)会优先执行子类的方法,子类没有的时候才会执行父类的方法。
2)如果想调用父类的方法,那么可以使用super.方法名();
3)super(name,score);//调用父类中带两个参数的构造方法
N.B:a.调用父类中的构造方法必须放在该类中的第一行,调用父类中的普通方法则无此讲究。
b.当左边出现三角形符号说明重写父类的方法成功。
四、自动转型
exp:
父类 对象名 = new 子类();
Student stu = new UNStudent("无名",5);
1.为什么父类无法调用子类自己定义的方法?
答:简单的说就是,儿子可以继承父亲的所有财产,而父亲却不可以干涉儿子的财产。
2.为什么Java还会保留自动转型呢?
答:为了扩大使用范围。
exp: 学校有英语老师,教的是大学生,但她也可以去教高中生,初中生,小学生,幼儿园的学生,其他类的学生。
teach(UNStudent un){
大学生
}
teach(XStudent un){
小学生
}
teach(Student stu){
stu.study();
}
五、多态
1.概念:一个方法名可以通过不同参数(参数名,参数个数)来重复使用,表示不同的意思。即一个名字多种功能用法。
2.多态的实现:相同类型的对象调用相同方法的时候,由于继承和重写机制,得到的结果不一定相同。只有到运行时,才知道到底是什么。
3.多态和
重载的区别:重载是多态的一部分
/************************练习*****************************/
回合制游戏:奥特曼和小怪兽要战斗,直到一方的血量为0的时候结束战斗,输出谁胜利了!
奥特曼除了可以打小怪兽外,还可以攻击其他的奥特曼对象。
小怪兽除了可以打奥特曼外,还可以攻击其他的小怪兽对象。
1. 思路:先定义一个角色类作为父类,再定义一个奥特曼类和一个小怪兽类作为角色类的子类。在奥特曼类中定义两个奥特曼对象,在小怪兽类里同样也定义两个小怪兽对象。最后在主函数中调用它们父类中的战斗方法,模拟战斗场景。
2. 分析:
对象:
正版奥特曼、盗版奥特曼、小怪兽1号、小怪兽2号
特征:姓名、属性
行为:战斗
3. 具体代码如下:
1)package War;//定义一个角色类作为父类
public class Player {
private String name;//姓名属性
private int blood;//血量属性
/**
*name赋给姓名属性的参数
* blood赋给血量属性的参数
*/
public Player(String name,int blood){
this.name=name;
this.blood=blood;
}
//设置姓名属性值的方法
public void setName(String name){
this.name=name;
}
//获取姓名属性值的方法
public String getName(){
return name;
}
//设置血量属性值的方法
public void setBlood(int blood){
this.blood=blood;
}
//获取血量属性值的方法
public int getBlood(){
return blood;
}
//定义一个战斗方法
public void fighting(Player player){
player.setBlood(player.getBlood()-1);
System.out.println(name+"攻击"+player.getName()+","+"对方血量减1,仅剩"+player.getBlood());
}
}
2)package War;//定义一个Aoteman类,它继承自Player类
public class Aoteman extends Player{
/**
* 调用父类中两个带参数的构造方法
*/
public Aoteman(String name,int blood){
super(name,blood);
}
}
3)package War;//定义一个Monster类,它继承自Player
public class Monster extends Player{
/**
* 调用父类中两个带参数的构造方法
*/
public Monster(String name,int blood){
super(name,blood);
}
}
4)package War;//定义一个战斗类,模拟战斗场景
public class Fight {
/**
* 定义一个入口主函数
*/
public static void main(String[] args) {
//实例化Aoteman类的对象
Aoteman zbao=new Aoteman("正版奥特曼",10);
Aoteman dbao=new Aoteman("盗版奥特曼",5);
//实例化Monster类的对象
Monster mon1=new Monster("小怪兽1号",5);
Monster mon2=new Monster("小怪兽2号",3);
/******************开始战斗************************/
//先令正版奥特曼与小怪兽1号战斗
while(mon1.getBlood()>0&&zbao.getBlood()>0){
zbao.fighting(mon1);
//如果小怪兽1号的血量值为0,输出结果,进入下一
循环
if(mon1.getBlood()==0){
System.out.println("小怪兽1号战死!正版奥特曼胜利!他将与盗版奥特曼战斗!");
while(dbao.getBlood()>0&&zbao.getBlood()>0){
zbao.fighting(dbao);
dbao.fighting(zbao);
//如果正版奥特曼的血量为0,输出结果
if(zbao.getBlood()==0){
System.out.println("正版奥特曼战死!盗版奥特曼战胜!");
break;
}
//如果盗版奥特曼的血量为0,输出结果
else if(dbao.getBlood()==0){
System.out.println("盗版奥特曼战死!正版奥特曼战胜!");
break;
}
}
break;
}
mon1.fighting(zbao);
//如果正版奥特曼的血量值为0,输出结果,进入下一循环
if(zbao.getBlood()==0){
System.out.println("正版奥特曼战死!小怪兽1号胜利!它即将与小怪兽2号自相残杀!");
while(mon1.getBlood()>0&&mon2.getBlood()>0){
mon1.fighting(mon2);
mon2.fighting(mon1);
//如果小怪兽1号的血量为0,输出结果
if(mon1.getBlood()==0){
System.out.println("小怪兽1号战死!小怪兽2号战胜!");
break;
}
//如果小怪兽2号的血量为0,输出结果
else if(mon2.getBlood()==0){
System.out.println("小怪兽2号战死!小怪兽1号战胜!");
break;
}
}
break;
}
}
}
}
4.
写代码时应注意的问题:
a.不要老是忘记跳出循环了好不好!
b.不要老是想着把一些数据定死了(比如设定战斗次数)!为用户着想,也是为自己着想!
c.继承的时候,当
你需要“重写”的时候再加上带有“super”的东东,不然都不用写,你的子类已经继承好父类中的所有了亲!~
d.java里的语句一般是从上至下执行的,一些需要使用的参数要在使用前就定义好哦~