2013.07.11
上课内容:类的继承
说到类的继承,我们先来回顾一下类,类是具有一些相同或相似的物体的集合,是由属性和方法组成。
类的继承就是在我们先定义的类的基础上,定义一个类去继承原先类的属性和方法,并且可以新生成、改变原方法。
这样,我们就说原先的类为父类,新定义的类为主类。
继承的关键词:extends
用法:
public class 类名 extends 类名{
}
这里要注意一点,java里的类为单继承,即一个子类只允许有一个父类,但是一个父类可以有多个子类,每个子类可以用不同的方式重写父类的方法。
既然子类可以继承父类,我们下面来讨论一下子类可以继承到父类什么:
1、属性
2、方法
子类可以继承父类的所有属性和方法,但是要注意子类不能全部调用父类的属性和方法。
我们先来一个一个分析下访问修饰符的范围:
public 在类所在的java project内都可以调用
protected 在本类和其在同一个包下以及在不同包下的子类中都可以调用
默认(不加修饰符)在本包下可以调用
private 只能在本类中调用
明白了这些,我们就可以明白为什么子类不能全部调用父类的属性和方法,但是在重写时可以扩大父类的访问修饰符。
这样我们就要讲到方法的重写,这也是继承中很关键的以部分。
所谓类的重写,与方法重载类似,我们在父类中定义了一个方法,在子类中不仅可以继承其方法,也可以改变其方法
但是要注意在方法重写时,返回值数据类型,方法名,参数的个数,参数的类型,参数的顺序都要完全致。
还有就是要注意我们上面提到的重写时可以扩大访问修饰符而不能减小,否则会报错。
了解了方法重写,那么什么情况下才需要方法重写呢?
方法重写是在我们父类的方法不能满足我们现在的需求时,需要我们在父类的方法中进行一定的补充,这时我们就要用到方法的重写。
比如我们定义一个Student类,创建一个play方法玩的是LOL,但是我们想玩其他的游戏呢,就要新建一个子类继承父类,然后重载play方法,这样就ok啦!
要是我们想在子类的play方法中调用父类的play方法,就可以使用super.play();
知道了方法的重写,下面我们来看类型的转换,类型的转换前提是要求必须要有继承关系,而且一般是由小转大。
我们在第一节课中知道,当定义两个不同的数据类型时,小的可以向大的转换叫做向上转型,而大的则要强制向小的转化叫做向下转型。
举个例子:
byte a;
int b = a;
short c = (short)b;
类中的类型转换也是如此。
类型的转换的一般格式是
向上转型:父类名 对象名 = new 子类名();
向下转型:子类名 对象名 = (子类名)对象;
但是要注意一点,就是转换后的对象无法调用子类的方法,在调用父类的方法时若在子类的方法中重写,则会调用子类对应的方法。
至于无法调用子类方法的原因,主要是因为eclipse编译的机制问题,对象是属于父类,软件会在父类中找你调用的方法,一旦找不到就会报错。
知道了类的自动转型,那么它究竟有什么好处呢?我们举个例子:
一个大学英语老师可以教大学生、高中生、初中生、小学生英语,
那么对这个大学英语老师我们就要创建4个不同的方法,这显然不是我们希望看到的。
所以我们只需要创建一个方法为大学英语老师教学生。
这样就可以让大学生、高中生、初中生、小学生继承学生类,然后定义一个老师教学生的方法就可以了。
练习:回合制游戏:德玛(致命打击 勇气 审判 德玛西亚正义(技能名和攻击力))+卡牌(万能牌 选牌 卡牌骗术 命运(技能名和攻击力))要去战斗,直到一方的血量为0的时候结束战斗,输出谁胜利了。
德玛和德玛战斗
卡牌和卡牌战斗
大致思路是这样的:建立一个英雄类,拥有名字,技能,防御,血量的属性,拥有设置、获取各个属性的方法,还有的就是要使用的攻击方法。
然后分别定义Garen和Twisted两个类来继承英雄类,并且定义自己的攻击防御和血量,并初始化姓名。
定义一个技能类,技能拥有名字和攻击力两个属性,拥有设置、获取各个属性的方法。
下面我们就可以在主函数中调用我们定义的方法来实现回合制战斗啦~
附代码如下:
package cn.tth.pratice0711; /** * 总控制台 * @author TTH * */ public class LOL { public static void main(String[] args) { //初始化两个人的技能对象 Skill[] gskill={new Skill("普通攻击",56),new Skill("致命一击",30),new Skill("勇气",40), new Skill("审判",60),new Skill("德玛西亚正义",175) }; Skill[] tskill = {new Skill("普通攻击",46),new Skill("万能牌",60),new Skill("选牌",40), new Skill("卡牌骗术",55),new Skill("命运",200)}; //初始化两个战斗对象 Garen garen = new Garen("Garen",gskill); Twisted twisted = new Twisted("Tweisted",tskill); //输出盖伦对卡牌 System.out.println(garen.getName()+" vs "+twisted.getName()); //进入回合制的循环 while(true){ //盖伦攻击卡牌 garen.Attack(twisted); //如果卡牌的血量小于等于0,结束回合制游戏 if(twisted.getHp()<=0){ System.out.println(garen.getName()+"win!"); break; } //卡牌攻击盖伦 twisted.Attack(garen); //如果盖伦的血量小于等于0,结束回合制游戏 if(garen.getHp()<=0){ System.out.println(twisted.getName()+"win!"); break; } } //初始化盖伦对象 Heros garen1 = new Garen("Blue Garen",gskill); Heros garen2 = new Garen("Purple Garen",gskill); //输出蓝色方盖伦对紫色方盖伦 System.out.println(garen1.getName()+" vs "+garen2.getName()); //进入回合制的循环 while(true){ //蓝色方盖伦攻击紫色方盖伦 garen1.Attack(garen2); //如果紫色方盖伦的血量小于等于0,结束回合制游戏 if(garen2.getHp()<=0){ System.out.println(garen1.getName()+"win!"); break; } //紫色方盖伦攻击蓝色方盖伦 garen2.Attack(garen1); //如果蓝色方盖伦的血量小于等于0,结束回合制游戏 if(garen1.getHp()<=0){ System.out.println(garen2.getName()+"win!"); break; } } //初始化卡牌对象 Heros twisted1 = new Twisted("Blue Twisted",tskill); Heros twisted2 = new Twisted("Purple Twisted",gskill); //输出蓝色卡牌伦对紫色方卡牌 System.out.println(twisted1.getName()+" vs "+twisted2.getName()); //进入回合制的循环 while(true){ //蓝色方卡牌攻击紫色方卡牌 twisted1.Attack(twisted2); //如果紫色方卡牌的血量小于等于0,结束回合制游戏 if(twisted2.getHp()<=0){ System.out.println(twisted1.getName()+"win!"); break; } //紫色方卡牌攻击蓝色方卡牌 twisted2.Attack(twisted1); if(twisted1.getHp()<=0){ System.out.println(twisted2.getName()+"win!"); break; } } } } package cn.tth.pratice0711; import java.util.Random; /** * 英雄类 * @author TTH * */ public class Heros { //定义姓名属性 private String name = new String(); //定义攻击属性 private int atk; //定义防御属性 private double def; //定义血量属性 private double hp; //定义技能数组 private Skill[] skill; //定义一个随机数 private Random ran = new Random(); //设置姓名的方法 public void setName(String name){ this.name=name; } //调用姓名的方法 public String getName(){ return name; } //设置攻击的方法 public int getAtk() { return atk; } //调用攻击的方法 public void setAtk(int atk) { this.atk = atk; } //设置防御的方法 public double getDef() { return def; } //调用防御的方法 public void setDef(double def) { this.def = def; } //设置血量的方法 public double getHp() { return hp; } //调用血量的方法 public void setHp(double hp) { this.hp = hp; } //设置血量 public void setSkill(Skill[] skill){ this.skill = skill; } //得到血量 public Skill[] getSkill(){ return skill; } //设置攻击方法 public void Attack(Heros hero){ //得到一个长度跟skill相同的随机数 int r=ran.nextInt(skill.length); //设置攻击 hero.setHp(hero.getHp()-skill[r].getAtk()*(1-hero.getDef()/100.0)); //如果血量小于零,设置为0 if(hero.getHp()<=0){ hero.setHp(0); } //输出技能攻击后的血量 System.out.println(name+"释放技能"+skill[r].getName()+","+hero.getName()+"血量为"+(int)hero.getHp()); } } package cn.tth.pratice0711; /** * 技能类 * @author TTH * */ public class Skill { //技能名 private String name; //技能攻击 private int atk; //skill构造函数 public Skill (String name,int atk){ this.name = name; this.atk = atk; } //获取技能名 public String getName() { return name; } //设置技能名 public void setName(String name) { this.name = name; } //获取技能攻击力 public int getAtk() { return atk; } //设置技能攻击力 public void setAtk(int atk) { this.atk = atk; } } package cn.tth.pratice0711; /** * 盖伦类,继承英雄类 * @author TTH * */ public class Garen extends Heros { /** * 构造函数 * @param name英雄名字 * @param skill英雄技能数组 */ public Garen(String name,Skill[] skill){ this.setDef(19); this.setHp(455); this.setName(name); this.setSkill(skill); } } package cn.tth.pratice0711; /** * 崔斯特类,继承英雄类 * @author TTH * */ public class Twisted extends Heros { /** * 构造函数 * @param name英雄名字 * @param skill英雄技能数组 */ public Twisted(String name,Skill[] skill){ this.setDef(11.25); this.setHp(384); this.setName(name); this.setSkill(skill); } }
相关推荐
`Student`类继承`Person`,增加学号属性,并重写`showInfo()`方法。同时,我们需要提供带参数和不带参数的构造方法为父类和子类的属性赋值。 3. **动物世界继承**:设计一个`Animal`类,它有吃、睡和移动的行为。...
了解这些概念后,我们可以看到`GenericClass.java`文件可能包含了关于如何创建和使用继承泛型类的实际代码示例。而`Java.jpg`可能是用于辅助解释的图像,比如类结构图或代码截图。在实际学习过程中,结合代码和图像...
JavaIO类InputStream/OutputStream继承关系图,使您对IO类一目了然
2. 尽管Java在类继承上是单继承的,但可以通过实现多个接口来实现多重继承的效果,接口是Java中另一种形式的继承,它允许一个类实现多个接口。 3. 子类继承了父类的所有非私有成员变量和方法,但不包括构造函数。...
Java集合类的继承关系MindManager
java ApplicationContext类继承体系.jpg
制作本文档的目的是将类的继承关系可以打印成书,直观了解继承关系图,同时还罗列出接口继承与实现关系图及枚举继承图(其中枚举放于最后两页)。 我已用该文档装订了一本书,作为自己学习java的参考,希望快速提供...
继承是 Java 中的一种机制,允许一个类继承另一个类的属性和方法。继承的语法是使用 `extends` 关键字,例如 `public class Child extends Parent`。在 Java 中,只支持单一继承,也就是说一个类只能有一个直接父类...
2. 多重继承:一个子类可以继承多个父类,但 Java 语言中的类只支持单继承,而接口支持多继承。 继承的应用场景: 1. 代码重用:继承可以使得子类继承父类的代码,使得代码更加简洁和易维护。 2. 类之间的关系:...
类的继承格式、继承的关系表示图、访问限制、子类对象的实例化过程、方法的覆写、属性的覆盖、Super关键字、this与super的区别
南师大教育技术学考研南邮java实验二类继承笔记_JavaScript入门经典
java集合继承结构图
Java中的继承是面向对象编程的一个核心特性,它允许一个类(子类)继承另一个类(父类)的属性和方法,从而实现代码的复用和扩展。在这个"java关于继承的思维导图(Xmind)"中,我们可以看到作者对Java继承机制的详细...
Java --- 继承、抽象类
在Java中,继承是单继承的,即一个类只能直接继承一个父类,但可以通过接口实现多继承的效果。继承提高了代码的复用性,使得类层次结构更加清晰。 接口与继承的关系密切。一个类可以同时实现多个接口,也可以继承一...
java封装 继承与多态 程序设计 类与对象
java 中各种流的继承关系,图片介绍的再一目了然不过了
Java 继承是 Java 面向对象编程语言中的一种机制,通过继承,可以让一个类继承另一个类的属性和方法,从而实现代码的重用和继承关系的建立。本文将通过一个练习题,来详细介绍 Java 继承的使用和实现。 一、继承的...
一个使用了接口,抽象类,继承的JAVA类,模拟了计算机的组装过程