1 继承
- 继承是面向对象最显著的一个特征
- 继承是从已有类派生出新类.使用extends关键字
- 子类不能继承父类的构造方法以及父类的私有资源
- 子类不能有选择的继承父类的属性及方法
- 一个子类只能有一个父类,一个父类可以多个子类.可以顺序继承
- 父类的私有资源对于子类来说是不可用,但是私有资源被父类公有资源调用时,子类通过父类公有资源隐式的使用父类私有资源.
- 子类构造方法默认调用父类的无参构造,当父类没有无参构造或者父类无参构造不可见时.必须在子类构造方法内显式的调用至少一个父类可用的构造方法
- 是is-a的关系
小tips: 面向对象程序设计与面向对象设计的领域里,is-a(英语:subsumption,包含架构)指的是类的父子继承关系,例如类D是另一个类B的子类(类B是类D的父类)。
1.1 语法格式
class Fo{//创建父类Fo } class So extends Fo{//创建子类So继承Fo }
1.2 练习:继承入门案例
public class TextExtends {
/**
* 1.创建一个父类Animal,设置name,weight属性以及scream方法
* 2.创建一个子类Cat 继承父类Animal.
* 3.调用子类继承父类的属性及方法
*/
public static void main(String[] args) {
Cat c = new Cat();
System.out.println("name:"+c.name+",weight:"+c.weight);
c.scream();
}
}
class Animal{
String name="动物";
double weight;
public void scream() {
System.out.println("动物会叫");
}
}
class Cat extends Animal{
}
运行结果:
name:动物, weight:0.0动物会叫
2 关键字super
代表父类对象的一个引用
2.1 语法格式
super.a//调用父类属性 super.pritnt()//调用父类方法 super()//调用父类构造
- 父类构造方法的调用,必须在子类构造方法内的第一行
3 方法重写override
- 在子类继承父类方法后,在子类需要针对父类方法进行修改时.就要使用方法重写.
- 当子类内的方法与父类内的方法签名一致时就完成了方法重写
方法签名:
返回值类型 方法名 (参数列表)
小tips:部分方法签名的说法不包含返回值类型
练习
1 练习:成员变量的使用
public class TextExtends1 {
/**
* 1.定义一个父类Math,拥有属性int a
* 2.定义一个子类Sum ,拥有属性int a
* 3.子类中定义两个sum方法 sum1其中sum1计算父类属性a和子类属性a的和值
*/
public static void main(String[] args) {
Sum s =new Sum();
s.sum1();
}
}
class Math{
int a= 10;
}
class Sum extends Math{
int a= 1;
public void sum1() {
System.out.println(super.a+a);
}
}
运行结果:
11
2 练习:成员方法的使用
public class TextExtends2 {
public static void main(String[] args) {
//3.创建子类对象进行测试
Son2 s =new Son2();
/**
* 1.子类继承了父类,可以实现父类所有功能
*/
s.eat();
/**
* 2.继承后,子类不仅可以使用父类的功能,还可以使用自己特有的功能,实现功能的拓展
*/
s.study();
}
}
//1.创建父类
class Father2{
public void eat() {
System.out.println("爸爸爱吃肉!");
}
}
//2.创建子类
class Son2 extends Father2{
//4.1 提供子类特有方法
public void study() {
System.out.println("正在努力学习!");
}
/**
* OCP原则:面向修改关闭,面向拓展开放--只允许功能拓展,不允许修改原来的代码
*/
//5.对父类功能进行修改--不允许直接修改父类原有业务
//功能修改--方法的重写override
/**
* 3.重写:和父类的方法签名[返回值类型 方法名(参数列表)]保持一致,void eat()一模一样,修改是子类的功能,父类的功能并没有发生改变
* 4.重写时,子类必须有权限取重写父类的功能,父类的私有方法无法被重写
* 修改的方法修饰符>=父类方法修饰符
*/
public void eat() {
System.out.println("儿子爱蔬菜!");
}
}
运行结果:
儿子爱蔬菜! 正在努力学习!
3练习:构造方法的使用
/**
* 本类用于测试继承中构造方法的使用 总结:
* 1.子类创建对象时,默认会访问父类无参构造
* 2.在子类构造方法中第一行都有一天默认Super()--调用无参构造
* 3.当父类没有无参构造时,可以通过Super调用其他父类构造方法
* 4.构造方法不可以被继承
*/
public class TestExtends3 {
public static void main(String[] args) {
// 4.创建父类对象
// Father3 f = new Father3();
// 6 创建子类对象
Son3 s = new Son3();
}
}
//1. 创建父类
class Father3 {
/**
* 0.构造语句可以被继承吗?不可以 语法结构的要求:构造方法的方法名需要本类一致,天然就不符合要求
*/
// 5. 手动添加父类无参构造
public Father3() {
System.out.println("父类无参构造");
}
// 8.创建父类含参数构造
public Father3(String s) {
System.out.println("父类无参构造" + s);
}
}
//2.创建子类
class Son3 extends Father3 {
// 7.创建该子类的构造方法
public Son3() {
/**
* 1. 子类的构造方法中默认存在super(),所以创建对象时,默认会调用父类的无参构造
* 2.子类在创建对象时,会自动调用子类的无参构造
* 但是继承后,会先去调用父类的无参构造,在执行自己构造方法中的功能
*/
/**
* 3, 当父类中没有无参构造时,调用的是父类的含参数构造 必须要调用一个父类的构造函数
*/
super("红烧肉");
System.out.println("Son2无参构造");
}
}
运行结果
父类无参构造红烧肉 Son2无参构造