面向对象之继承
学习要点:
- 掌握继承的优点和实现方法
- 掌握子类重写父类的方法
- 掌握继承条件下构造方法的执行过程
一、为什么需要继承
观察两个类:
苹果类
public class Apple {
String name;
String color;
String brand;
public void print(){
System.out.println(brand+"牌的"+name);
}
}
橙子类
public class Orange {
String name;
String size;
String brand;
public void print(){
System.out.println(brand+"牌的"+name);
}
}
类图:
我们发现,这边两个类,很多的属性相同,方法也是相同的
面向对象解决的就是代码重复的问题
上面的String name、String brand重复了,我们就应该抽取出来
我们的代码可以复用,不能重复。
怎么解决呢?---->继承
看类图
将我们觉得共有的属性提取出来,另找一张图纸使Apple与Fruit产生关系
调用的时候将Apple和Fruit看成一张图纸即可
二、继承是啥
简单来说,就是将一个品种的类,相同的属性、方法抽取出来,形成一个父类
让子类继承父类,那些重复的代码只需要在父类出现一次即可
现实意义:
定义:
- 继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。
王者荣耀中的角色体系
英雄是父类 --属性:名字,性别,价格,攻击力 行为:攻击、防御
子类有各个职业,比如战士、法师、射手、刺客
战士:一次攻击个数 射手:攻击距离
总结出各个子类共有的属性,就是父类的属性。
三、如何使用继承
我们刚才已经学会抽取共有的属性
现在学习
1、编写父类
编写父类和之前学习的编写类,是一个玩意
我们就以一开始的水果类为模板
首先水果类
public class Fruit {
public String name;
public String brand;
public void print(){
System.out.println(brand+"牌的"+name);
}
}
2、让子类继承父类
首先语法是:
public class [类名] extends [父类名]
使用extends关键字,让子类继承父类
就一开始的苹果和橙子
苹果
public class Apple extends Fruit{
String color;
}
橙子
public class Orange extends Fruit{
String size;
}
四、何时使用继承
我们知道了为啥使用继承,也知道了怎么使用继承
但是我们该在哪里、什么时候使用继承呢?
条件一、有共有的属性和方法的时候
正如刚才的两个水果,有相同的属性之后
我们进行了抽取,抽取出了父类
但是这样还是条件不够
名字和品牌,有这两个属性的类是不是很多啊
衣服,手机,电脑
我们该怎么区分呢
条件二、符合is-a原则
什么是is-a原则:
刚才的苹果is-a水果,橙子is-a水果
满足两个条件的时候,就可以进行父类抽取了
条件三、一个类只能继承一个父类
这是对类继承的要求、不过多讲解
五、理解继承
1、删除父类方法中,子类相关的属性
提取过程中,对于公共方法中调用非公共属性的语句,需要稍作调整
2、子类继承了父类的哪些东西
实际上问题应该是这个:子类可以继承父类的所有些资源吗?
肯定是不能的。
首要的就是private修饰的属性、方法,这个大家肯定知道私有的
第二默认的修饰符下,子类和父类不在同一个包内的情况
第三父类的构造方法
除了这三个,其他的都是可以的
为了在不同包继承,但又不是所有类可以调用的情况
我们之前提过的protected就是用在这里的
只要继承就能继承到protected修饰的方法属性
访问修饰符 | 本类 | 同包 | 子类 | 其他 |
---|
private | √ | | | | 默认 | √ | √ | | | protected | √ | √ | √ | | public | √ | √ | √ | √ |
3、super关键字
我们知道,我们不能继承父类的构造函数,但是很多构造在父类已经写过了,再写不就又代码重复了么
所以java给了我们super关键字
当我们需要调用父类的构造方法的时候,需要在子类的构造方法中使用super();这是无参的,有参的加入参数即可 且必须是第一句
想调用个别属性的时候使用super.[父类属性名]的方式
想在子类中调用父类方法的时候也可以使用super.[父类方法名]的方式
例子:
public Apple(){
super();
super.brand="大品牌";
}
public Apple(String name){
super(name);
}
public void test(){
super.print();
}
-
在构造方法中,如果出现this或super关键字,则只能是该方法的第一条语句 -
在一个构造方法中,不允许同时使用this和super关键字调用构造方法 -
在类方法中,不允许出现this或super关键字 -
在实例方法中,this和super语句不要求是第一条语句,可以共存
4、方法的重写(Overriding)
刚才的水果类中,我们想要在水果类的print()方法,输出品牌和名字的同时,还想要输出苹果的颜色,橙子的大小等信息
在父类的方法中肯定是无法实现的
这就涉及到继承的一个特点了
就是方法的重写
4.1、重写的定义
-
意义:在子类中,根据需求对从父类继承的方法体进行重新编写,以实现子类需求 -
子类中出现与父类,方法声明完全一样的方法,就是重写 -
方法名,参数列表,返回值类型都一样,权限修饰符不能比父类方法更弱,方法体不同
4.2、注意点
- 重写方法和被重写方法必须具有相同的方法名
- 重写方法和被重写方法必须具有相同的参数列表
- 重写方法返回值类型必须和被重写方法的返回值类型相同或为其子类
- 重写方法不能缩小被重写方法的访问权限
4.3、示例
public class Apple extends Fruit{
String color;
public void print(){
super.print();
System.out.println("颜色是"+color);
}
}
4.4、重写和重载的区别
| 位置 | 方法名 | 参数表 | 返回值 | 访问修饰符 |
---|
方法重载 | 同类 | 相同 | 不相同 | 无关 | 无关 | 方法重写 | 子类 | 相同 | 相同 | 相同或是其子类 | 不能比父类更严格 |
六、Object类
Object类是所有类的祖先
是在java.lang包底下的
在定义一个类时,如果没有使用extends关键字,即没有显式地继承某个类,那么这个类直接继承Object类
常用方法
方法 | 说明 |
---|
toString() | 返回当前对象本身的有关信息,返回字符串对象 | equals() | 比较两个对象是否是同一个对象。若是,返回true | clone() | 生成当前对象的一个副本,并返回 | hashCode() | 返回该对象的哈希代码值 | getClass() | 获取当前对象所属的类信息,返回Class对象 |
java.lang.String类重写了Object类中的equals()方法,用于比较两个字符串的值是否相等
七、练习
设计编写王者荣耀/英雄联盟英雄关系
要求:1、使用继承
? 2、重写方法
? 3、写出父类Hero、子类战士Fighter、射手Shooter
类图如下
八、总结
|