1.继承
1.继承的关键字extends, 格式: class 子类 extends 父类{ }
子类又叫派生类,父类又叫超类
2.java只支持单继承,一个子类只能有一个父类,但一个父类可以用多个子类。
3.继承具体传递性,爷爷的功能会给到爸爸,爸爸的功能会给到孙子。
4.子类可以修改父类的功能,也可以拥有自己独有的方法,实现功能的拓展,青出于蓝而胜于蓝***。
5.子类在继承父类以后,相当于把父类的功能进行了复制,包括属性和方法;但是父类的私有资源(private属性、方法)都不会被子类继承。构造方法不可被继承,由于构造方法的定义所致。
6.继承是一个is a 的关系,比如小猫是小动物,DingDang是一只猫,宝马是汽车;
要求子类必须是父类的一种继承结构,依赖性非常强,强耦合。
练习:测试继承的入门案例:动物--猫--DingDang
package cn.tedu.oopextends;
/**本类用于继承的入门案例*/
public class TestExtendsDemo {
public static void main(String[] args) {
//5.创建Animal类/Cat类/MiaoMiao类的对象
Animal a =new Animal();//a只是存放地址值的引用对象
Cat c = new Cat();
MiaoMiao m= new MiaoMiao();
//6.利用3个对象调用Animal类的方法
a.eat();
c.eat();
m.eat();
/**3.继承具有传递性,爷爷的功能会传给爸爸,爸爸的功能会传给孙子*/
}
}
//1.创建爷爷类Animal
class Animal{
//4.定义爷爷类的普通方法
public void eat(){
System.out.println("动物都需要进食~~");
}
}
//2.创建父类Cat,并与Animal类建立继承关系
/**1.我们通过extends建立子类与父类的继承关系,格式:class 子类 extends 父类{}
* 2.java只支持单继承:一个字类只能有一个父类,但一个父类可以有多个子类
* 7.继承是一种is a 的关系,比如小猫是小动物,DingDang是猫,宝马是汽车
* 要求子类必须是父类的一种继承结构,依赖性非常强,强耦合*/
class Cat extends Animal {
//7.属性--成员变量
int a = 10;
private int b = 100;
}
//3.1创建孙子类DingDang,与Cat类建立继承关系
class DingDang extends Cat{
/**4.子类可以拥有自己独有的方法,实现功能的扩展,青出于蓝而胜于蓝*/
public void studyJava(){//打印语句一定要放在方法里
/**5.子类在继承父类以后,相当于把父类的功能进行了复制*/
System.out.println(a);
/**6.父类私有资源,子类不能使用,原因是私有资源封装不可见*/
//System.out.println(b);//子类不可使用父类的私有资源
}
}
//3.2//创建孙子类MiaoMiao,与Cat类建立继承关系
class MiaoMiao extends Cat {
}
2.super(关键字)
1.super是一个关键字
2.super代表的是父类的一个引用,可以把它看成是Father super=new Father();
3.如果子类与父类的成员变量同名时,使用" super. " 指定的是本类父类的成员变量,不同名时可以直接使用父类成员变量System.out.println(父类成员变量名);
练习1:测试继承中super对成员变量的调用(子父成员变量同名时)
格式: System.out.println(super.父类成员变量名);
package cn.tedu.oopextends;
/**本类用于测试继承中成员变量的使用*/
public class TestExtends1 {
public static void main(String[] args) {
//8.创建Son类的对象
Son s = new Son();
s.eat();
}
}
//1.创建父类
class Father{
//3.定义父类的属性---成员变量
int sum = 1000;
int count = 100;
}
//2.创建子类,并与父类建立继承关系
class Son extends Father{
//4.定义子类中的属性--成员变量
int sum = 100;
//5.定义子类的功能---普通方法
public void eat(){
//6.定义子类中的局部变量
int sum = 10;
//7.测试变量的打印结果
System.out.println(sum);//10,变量的就近原则
System.out.println(this.sum);//100,使用this调用(指定)的是本类的成员变量
/**在子类中使用父类的sum资源,但是出现重名的sum变量,那就需要使用”super.“进行指定
* super是关键字 可以理解成父对类对象的引用,比如:Father super = new Father()*/
System.out.println(super.sum);//1000,super指定的是父类的成员变量
System.out.println(count);//没有重名的变量,直接打印输出即可
}
}
练习2:测试继承中super对构造方法的使用
注意:在构造方法里,super(参数列表);出现的调用位置必须是第一行
格式:在子类构造方法第一行,super(参数列表);
1.在创建子类对象时,会调用构造方法,而子类构造方法中的第一行就是super();
即:创建子类对象,会先调用父类的构造方法
2.子类构造方法中必须调用父类无参构造,如果没有无参构造,需要手动调用父类的其他构造方法
3.构造方法不可以被继承
4.super()--表示调用父类的无参构造
super("")--表示嗲用父类的含参构造,此处举例是一个String类型的参数
package cn.tedu.oopextends;
/**本类测试继承中构造方法的使用*/
public class TestExtends3 {
public static void main(String[] args) {
//3.son类的对象
Son2 s2 = new Son2();
}
}
//1.创建父类
class Father2{
/**构造方法可以被继承吗?不可用
* 原因:由于构造方法的语法要求,构造方法必须与类同名
* 不能在子类有一个父类名字的构造方法,天然不符合要求*/
//5.提供父类的无参构造
// public Father2(){
// System.out.println("我是父类的无参构造~");
// }
public Father2(String s){
System.out.println("父类的含参构造"+s);
}
}
//2.创建子类并与父类建立继承关系
class Son2 extends Father2{
/**在子类的构造方法中默认存在super();表示调用父类的无参构造
* 也就是说,在创建子类对象时,会去调用子类的构造方法,继承后,
* 会先去调用父类的构造方法,再去调用子类的构造方法
*/
//4.创建子类的无参构造
public Son2(){
super("");//表示调用父类的无参构造
/**当父类中没有无参构造时,调用的是父类的含参构造
* 子类不关心具体调用的是父类的哪个构造函数
* 只是必须调用一个父类的构造函数而已*/
System.out.println("我是Son2的无参构造~~");
}
}
练习3:测试继承中super对普通方法【成员方法】的使用
格式:如果发生了重写后,子类又想使用父类的功能(方法)时,使用super.父类方法 名(参数列表);
注意:这里需要重写(指发生了继承关系以后(两个类),子类去修改父类原有的功能)
***方法重写Override***
1. 继承以后,子类就拥有了父类的功能
2. 在子类中,可以添加子类特有的功能,也可以修改父类的原有功能(这个过程叫重写)
3. 子类中方法的签名(方法名+参数列表)与父类完全一样时,会发生覆盖/复写的现象
4. 格式要求:方法的返回值 方法名 参数列表 要完全一致,就方法体是重写的
注意: 父类的私有方法不能被重写,因为私有资源不可见;
子类重写父类方法时,子类修饰符要大于等于父类修饰符的权限
5.重写规则:两同:方法名与参数列表要和父类保持一致
两小:子类方法的返回值类型<=父类方法的返回值类型
子类方法抛出的异常类型<=父类方法抛出的异常类型【未学到】
一大:子类方法修饰符>=父类方法的修饰符
注意:权限修饰符范围详见面向对象
package cn.tedu.oopextends;
/**测试继承中成员方法的使用*/
public class TestExtends2 {
public static void main(String[] args) {
//4.创建父类与子类的对象进行测试
Father1 f = new Father1();
Son1 s =new Son1();
f.eat();
/**1.继承后,子类可以使用父类的所有非私有资源*/
s.eat();
s.study();
s.play();
}
}
//1.父类
class Father1{
//3.创建父类方法
public void eat(){
System.out.println("爸爸爱吃肉~");
}
public void play(){
System.out.println("爸爸爱踢足球");
}
}
//2.子类,与父类建立继承关系
class Son1 extends Father1{
//5.创建子类特有的功能
public void study(){
System.out.println("快到端午了,学学包粽子吧11");
}
/**OCP原则:面向修改关闭,面向拓展开放
* 只允许功能拓展,不允许修改原来的代码*/
//6.修改父类原有的功能--不允许修改父类中的原代码
/**功能修改--方法的重写
* 重写方法的规则:
* 和父类的方法签名保持一致【方法名&参数列表】
* 除此之外,子类方法的修饰符要>=(大于等于)父类方法的修饰符
* 子类返回值类型要<=(小于等于)父类的返回值类型
* 然后去修改子类中本方法的实现,父类的功能并没有被改变
* 重写时,子类必须拥有可以重写的权限,子类无权修改父类的私有方法
*/
@Override/**这是一个注解,可以理解成一个标签,用来标记此方法是不是一个重写的方法,
*能加注解就证明是个正确的书写方法*/
public void eat(){
super.eat();//如果发生了重写,还想用父类的功能,
//需要使用Super.+父类的(方法名+参数列表)来调用
System.out.println("儿子爱吃蔬菜!!");
}
public void play(){
System.out.println("我爱玩电子游戏");
}//子类无权修改父类的私有方法
}
3.拓展
3.1 this与super的区别
- This代表本类对象的引用:class Cat{ this.XXX } 可以理解成: Cat this = new Cat();
- super代表父类对象的引用:class Father{ } class Son extends Father{ super.XXX } 可以理解成: Father super = new Father();
- this可以在两个变量名相同时,用于区分成员变量和局部变量
- this 可以在本类的构造方法之间调用,位置必须是第一条语句,注意,不能相互调用,会死循环
- super是发生了继承关系以后,子类如果想用父类的功能,可以通过super调用
- 如果发生了重写,还想用父类的功能,需要使用super来调用
- Super在调用父类构造方法时,必须出现在子类构造方法的第一条语句,super默认调用父类无参构造,而且如果父类中没有提供无参构造,子类可以通过super来调用父类其他的含参构造
- this、super不能同时出现,因为都要在第一行
3.2重载Overload 与 重写Override 的区别
- 重载: 是指在一个类中的现象,是指一个类中有很多同名的方法,但是方法的参数列表不同
- 重写: 是指发生了继承关系以后(两个类),子类去修改父类原有的功能 语法规则:子类的方法签名(返回值类型 方法名(参数列表) )与父类一致 重写方法的修饰符: 子类修饰符>= 父类的修饰符
- 重载的意义: 是为了方便外界对方法进行调用,什么样的参数程序都可以找到对应的方法来执行,体现的是程序的灵活性
- 重写的意义:是在不修改源码的前提下,进行功能的修改和拓展 (OCP原则:面向【父类】修改关闭,面向【子类】拓展开放)