继承:关键字extends
java 中继承是单继承 允许多个子类继承一个父类,不允许一个子类继承多个父类。
继承是继承父类的所有属性和方法,但并不是所有的属性和方法都可被子类调用;
子类继承父类是必须写一个与父类相同的构造方法,否则会报错。当实例化一个子类对象时,实际上
既调用子类的构造方法又调用了父类的构造方法(父类构造方法再子类构造方法)。
父类有哪些属性和方法?
private 类{}中
默认的 包中
protected 包中和包外的子类
public 项目中
子类可调用父类的哪些属性和方法呢?
1)子类继承父类 主函数中可调用的 属性和方法(子类和父类在同一包下)
protected
public
默认的
2)子类继承父类 主函数中可调用的 属性和方法(子类和父类在不同包下)
public
3)在子类中能调用的属性和方法(子类和父类在同一包下)
默认的
protected
public
4)在子类中能调用的属性和方法(子类和父类在不同包下)
protected
public
方法重写的条件?
1、继承
2、返回值数据类型、方法名、参数类型、参数个数、参数顺序必须完全一致
3、子类重写方法时可以扩大访问修饰符的范围(或保持一致):小的可转换为大的
什么情况下使用方法重写?
当子类与父类的方法一样时,但产生相应的效果不一样,如父类 学生 有一方法study(){grade++} 学习后考试成绩增加 子类大学生
也应有一个相同的学习的方法,但大学生学习后产生的效果肯定与父类不同,此时就需用到方法重写,如 study(){grade++;score++;}
此时,大学生学习后不光考试成绩增加而且学分也增加。总而言之,若想子类与父类有相同的行为,但会产生不同的效果时,就要用到重写。
如何调用重写后的方法?
super关键字 可调用父类的方法
调用构造方法:super(参数);
调用方法: super.方法名;
自动转型
条件
必须存在继承关系
格式
父类名 对象名 = new 子类名();
例如:Student UNstudent = new UNstudent();
问题:无法调用子类的方法
原因:编译机制的问题,当调用方法时,系统会自动从父类中寻找相应的方法,若没有,则编译不通过,若有,则优先从子
类中调用相应的方法。(实际上实例化了两个对象(父类、子类),new 子类在内存中)
好处 (类似与多态中virtual用法)
大学英语老师教大学生,他也可以教高中生、初中生、小学生、幼儿园。
若没用到自动转型时:老师的teach方法
teach(大学生){study();}
teach(高中生){study();}
teach(初中生){study();}
teach(小学生){study();}
teach(幼儿园){study();}
若用到自动转型时:
teach(学生){study();}
生活中什么情况下是自动转型?
byte b = 10;
int i = b;
^ 动物类
| 哺乳动物
| 人类
人类是哺乳动物
哺乳动物是动物
人类是动物
多态:
多态指的是同一个父类由不同子类继承,如父类 Student 可由大学生UNstudent 小学生PRstudent ...继承,
相应的子类可调用父类相应的属性和方法,此时就不用将两个子类都共有的属性和方法,分开写在各自的类中,而可以直接从
父类中调用,这样可节省代码,减少代码的重复。
接口
定义接口的关键字是interface
格式
public interface 接口名 extends 接口,......{
//常量
public static final 数据类型 常量名 = 值;
//抽象方法
public 返回值数据类型 方法名(数据类型 数据名);//不能加大括号 若加了说明方法有具体实现
}
接口是多继承可同时继承多个接口,不能实例化对象
注意四点:
类去实现接口的关键字:implements
抽象类
定义抽象类的关键字:abstract class
格式:
public abstract class 抽象类名 extends 类名或抽象类名 implements 接口名,......{
//类中所有 的属性和方法
//接口中的常量和抽象方法
public abstract 返回值数据类型 方法名(数据类型 参数名,....);
}
抽象类也不能实例化对象
接口与抽象类的区别:抽象类中,可以定义已实现的方法,也可以定义像接口中没有实现的方法--继承的子类就必须实现;
接口中的方法必须实现。
Hero父类
子类继承自父类
程序主函数
java 中继承是单继承 允许多个子类继承一个父类,不允许一个子类继承多个父类。
继承是继承父类的所有属性和方法,但并不是所有的属性和方法都可被子类调用;
子类继承父类是必须写一个与父类相同的构造方法,否则会报错。当实例化一个子类对象时,实际上
既调用子类的构造方法又调用了父类的构造方法(父类构造方法再子类构造方法)。
父类有哪些属性和方法?
private 类{}中
默认的 包中
protected 包中和包外的子类
public 项目中
子类可调用父类的哪些属性和方法呢?
1)子类继承父类 主函数中可调用的 属性和方法(子类和父类在同一包下)
protected
public
默认的
2)子类继承父类 主函数中可调用的 属性和方法(子类和父类在不同包下)
public
3)在子类中能调用的属性和方法(子类和父类在同一包下)
默认的
protected
public
4)在子类中能调用的属性和方法(子类和父类在不同包下)
protected
public
方法重写的条件?
1、继承
2、返回值数据类型、方法名、参数类型、参数个数、参数顺序必须完全一致
3、子类重写方法时可以扩大访问修饰符的范围(或保持一致):小的可转换为大的
什么情况下使用方法重写?
当子类与父类的方法一样时,但产生相应的效果不一样,如父类 学生 有一方法study(){grade++} 学习后考试成绩增加 子类大学生
也应有一个相同的学习的方法,但大学生学习后产生的效果肯定与父类不同,此时就需用到方法重写,如 study(){grade++;score++;}
此时,大学生学习后不光考试成绩增加而且学分也增加。总而言之,若想子类与父类有相同的行为,但会产生不同的效果时,就要用到重写。
如何调用重写后的方法?
super关键字 可调用父类的方法
调用构造方法:super(参数);
调用方法: super.方法名;
自动转型
条件
必须存在继承关系
格式
父类名 对象名 = new 子类名();
例如:Student UNstudent = new UNstudent();
问题:无法调用子类的方法
原因:编译机制的问题,当调用方法时,系统会自动从父类中寻找相应的方法,若没有,则编译不通过,若有,则优先从子
类中调用相应的方法。(实际上实例化了两个对象(父类、子类),new 子类在内存中)
好处 (类似与多态中virtual用法)
大学英语老师教大学生,他也可以教高中生、初中生、小学生、幼儿园。
若没用到自动转型时:老师的teach方法
teach(大学生){study();}
teach(高中生){study();}
teach(初中生){study();}
teach(小学生){study();}
teach(幼儿园){study();}
若用到自动转型时:
teach(学生){study();}
生活中什么情况下是自动转型?
byte b = 10;
int i = b;
^ 动物类
| 哺乳动物
| 人类
人类是哺乳动物
哺乳动物是动物
人类是动物
多态:
多态指的是同一个父类由不同子类继承,如父类 Student 可由大学生UNstudent 小学生PRstudent ...继承,
相应的子类可调用父类相应的属性和方法,此时就不用将两个子类都共有的属性和方法,分开写在各自的类中,而可以直接从
父类中调用,这样可节省代码,减少代码的重复。
接口
定义接口的关键字是interface
格式
public interface 接口名 extends 接口,......{
//常量
public static final 数据类型 常量名 = 值;
//抽象方法
public 返回值数据类型 方法名(数据类型 数据名);//不能加大括号 若加了说明方法有具体实现
}
接口是多继承可同时继承多个接口,不能实例化对象
注意四点:
类去实现接口的关键字:implements
抽象类
定义抽象类的关键字:abstract class
格式:
public abstract class 抽象类名 extends 类名或抽象类名 implements 接口名,......{
//类中所有 的属性和方法
//接口中的常量和抽象方法
public abstract 返回值数据类型 方法名(数据类型 参数名,....);
}
抽象类也不能实例化对象
接口与抽象类的区别:抽象类中,可以定义已实现的方法,也可以定义像接口中没有实现的方法--继承的子类就必须实现;
接口中的方法必须实现。
Hero父类
public class Hero {
private String name;
private int Q;
private int W;
private int E;
private int R;
private int blood;
private char skill;
public Hero(String name,int blood,int Q,int W,int E,int R){
this.name = name;
this.blood = blood;
this.Q = Q;
this.W = W;
this.E = E;
this.R = R;
}
//返回名字的方法
public String getname(){
return name;
}
//返回血量的方法
public int getblood(){
return blood;
}
//返回攻击力的方法
public int getATK_Q(){
return Q;
}
public int getATK_W(){
return W;
}
public int getATK_E(){
return E;
}
public int getATK_R(){
return R;
}
//设置血量的方法
public void setblood(int blood){
this.blood = blood;
}
//设置攻击的方法
public void attack(Hero h,char skill){
if(skill=='Q'){
h.setblood(h.getblood()-this.getATK_Q());
System.out.println(this.getname()+"技能Q攻击了"+h.getname());
System.out.println(h.getname()+"的血量为:"+h.getblood());
}
else if(skill=='W'){
h.setblood(h.getblood()-this.getATK_W());
System.out.println(this.getname()+"技能W攻击了"+h.getname());
System.out.println(h.getname()+"的血量为:"+h.getblood());
}
else if(skill=='E'){
h.setblood(h.getblood()-this.getATK_E());
System.out.println(this.getname()+"技能E攻击了"+h.getname());
System.out.println(h.getname()+"的血量为:"+h.getblood());
}
else if(skill=='R'){
h.setblood(h.getblood()-this.getATK_R());
System.out.println(this.getname()+"技能R攻击了"+h.getname());
System.out.println(h.getname()+"的血量为:"+h.getblood());
}
}
//声明一个英雄战士函数
public void show(){}
}
子类继承自父类
public class Twisted extends Hero {
public Twisted(String name, int blood, int Q, int W, int E, int R) {
super(name, blood, Q, W, E, R);
}
public void show(){
super.show();
System.out.println("英雄:"+super.getname()+"/血量:"+super.getblood()+"/Q(万能牌)的攻击力:"+super.getATK_Q()
+"/W(选牌)的攻击力:"+super.getATK_W()+"/E(卡牌骗术)的攻击力:"+super.getATK_E()+"/R(命运)的攻击力:"+super.getATK_R());
}
}
public class Garen extends Hero{
public Garen(String name, int blood, int Q, int W, int E, int R) {
super(name, blood, Q, W, E, R);
}
public void show(){
super.show();
System.out.println("英雄:"+super.getname()+"/血量:"+super.getblood()+"/Q(致命打击)的攻击力:"+super.getATK_Q()
+"/W(勇气)的攻击力:"+super.getATK_W()+"/E(审判)的攻击力:"+super.getATK_E()+"/R(德玛西亚正义)的攻击力:"+super.getATK_R());
}
}
程序主函数
public class Battlefield {
/**程序入口主函数
* @param args
*/
public static void main(String[] args) {
Hero garen = new Garen("盖伦",1000,35,30,75,135);
Hero twisted = new Twisted("崔斯特",700,100,50,100, 200);
garen.show();
twisted.show();
while(garen.getblood()>0&&twisted.getblood()>0){
twisted.attack(garen, 'Q'); //卡牌用Q攻击
if(garen.getblood()<0){
System.out.println(garen.getname()+"被击杀!");
System.out.println(twisted.getname()+"拿到一血!!!!");
}
else {
garen.attack(twisted, 'Q'); //盖伦用Q攻击
if(twisted.getblood()<0){
System.out.println(twisted.getname()+"被击杀!");
System.out.println(garen.getname()+"拿到一血!!!!");
}
else{
twisted.attack(garen, 'W'); //卡牌用W攻击
if(garen.getblood()<0){
System.out.println(garen.getname()+"被击杀!");
System.out.println(twisted.getname()+"拿到一血!!!!");
}
else {
garen.attack(twisted, 'W'); //盖伦用W攻击
if(twisted.getblood()<0){
System.out.println(twisted.getname()+"被击杀!");
System.out.println(garen.getname()+"拿到一血!!!!");
}
else{
twisted.attack(garen, 'E'); //卡牌用E攻击
if(garen.getblood()<0){
System.out.println(garen.getname()+"被击杀!");
System.out.println(twisted.getname()+"拿到一血!!!!");
}
else {
garen.attack(twisted, 'E'); //盖伦用E攻击
if(twisted.getblood()<0){
System.out.println(twisted.getname()+"被击杀!");
System.out.println(garen.getname()+"拿到一血!!!!");
}
else{
twisted.attack(garen, 'R'); //卡牌用R攻击
if(garen.getblood()<0){
System.out.println(garen.getname()+"被击杀!");
System.out.println(twisted.getname()+"拿到一血!!!!");
}
else {
garen.attack(twisted, 'R'); //盖伦用R攻击
if(twisted.getblood()<0){
System.out.println(twisted.getname()+"被击杀!");
System.out.println(garen.getname()+"拿到一血!!!!");
}
}
}
}
}
}
}
}
}
}
}