继承与多态 Java
目录
1.继承
1.1 继承概念
继承机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加新功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。继承主要解决的问题是:类的共性的抽取,实现代码复用。
1.2 继承的语法
在Java中如果要表示类之间的继承关系,需要借助extends关键字,例如:
package demo1;
public class Dog extends Animal{
public void bark(){
System.out.println(this.name+"正在叫");
}
}
注意:
- 子类会将父类中的成员变量或者成员方法继承到子类中
- 子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则没必要继承
1.3 父类成员访问
1.3.1 子类中访问父类的成员变量
子类和父类存在同名变量的时候,优先访问子类的!(就近原则)
如果要访问父类的a,需要super关键字:
System.out.println("父类的a:"+super.a);
也可以实例化一个对象:
Base base = new Base();
System.out.println("父类的b:" + base.b);
1.3.2 子类中访问父类的成员方法
注意:
- 通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到则访问,否则编译报错。
- 通过派生类对象访问父类与子类中同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用方法时传递的参数选择合适的方法访问,如果没有则报错
super和this都可以通过.来访问成员变量和成员方法,通过()来访问构造方法
1.4 super关键字
该关键字主要作用:在子类方法中访问父类的成员
注意:只能在非静态方法中使用
使用super调用构造方法时,只能放在第一行,this()也必须在第一行,所以,this()和super()不能共存
1.5 子类构造方法
子类对象构造时,需要先调用基类的构造方法,然后执行子类的构造方法(先父后子)
当没有提供任何的构造方法的时候,Java中会提供目前屏蔽起来的代码
class AA {
/*public AA(){
}*/
}
class BB extends AA {
/* public BB(){
super();
}*/
}
但是只要写了任何一个构造方法,都不会自动提供。
public class Derived Base{
public Derived(){
//super();子类构造方法中默认会调用基类的无参构造方法
//用户没有写时,编译器会自动添加,而且super();必须是子类构造方法中第一条语句
//并且只能出现一次
}
}
1.6 super和this
相同点:
- 都是Java中的关键字
- 只能在类的非静态方法中使用,用来访问非静态成员方法和字段
- 在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在
不同点:
- this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象从父类继承下来部分成员的引用
- 在构造方法中,this(...)用于调用本类构造方法,super(...)用于调用父类构造方法,两种调用不能同时在构造方法中出现
- 构造方法中一定会存在super(...)的调用,用户没有写编译器也会增加,但是this(...)用户不写则没有
1.7 再谈初始化
package demo3;
public class Animal {
String name;
int age;
static {
System.out.println("static Animal");
}
{
System.out.println("实例代码块Animal{ }");
}
public Animal(String name,int age){
this.name=name;
this.age=age;
System.out.println("Animal()");
}
}
package demo3;
public class Dog extends Animal{
static {
System.out.println("static Dog");
}
{
System.out.println("实例代码块 Dog{ }");
}
public Dog(String name,int age){
super(name,age);
System.out.println("Dog()");
}
}
package demo3;
public class Cat extends Animal{
static{
System.out.println("static Cat");
}
{
System.out.println("实例代码块 Cat{ }");
}
public Cat(String name,int age){
super(name,age);
System.out.println("Cat()");
}
}
创建一个对象,先执行父类和子类的静态,再执行父类的实例和构造,最后执行子类的实例和构造。
创建两个对象,先执行一次父类和子类的静态,再执行对象一的父类和子类的实例和构造,最后执行对象二的父类和子类的实例和构造。
1.8 protected关键字
private只能在当前类使用(同一包同一类)
default同一个包下的类可以访问
public公开的,哪里都可以使用
protected在同一个包下可以使用,不同包的只有子类可以使用,非子类无法访问。
1.9 继承方式
Java不支持多继承,一个类只能继承一个父类
但是可以通过接口的形式支持多继承
一般不希望出现超过三层的继承关系,如果继承次数太多,就需要考虑对代码进行重构了。
1.10 final关键字
如果一个类不想被其他类继承,可以使用关键字final来修饰这个类,此时这个类叫做密封类。
如果使用final修饰变量,这个变量将不能被修改。
1.11 继承与组合
和继承类似,组合也是一种表达类之间的关系的方式,也能够达到代码重用的效果,组合并没有涉及到特殊的语法(诸如extends这样的关键字),仅仅是将一个类的实例作为另一个类的字段。
继承表示对象之间是is-a的关系,组合表示对象之间是has-a的关系
public Student[] students=new Student[10];
2. 多态
2.1 多态的概念
通俗来讲,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生不同的状态。
2.2 多态实现条件
再Java中要实现多态,必须满足以下几个条件,缺一不可:
- 必须在继承体系下
- 子类必须要对父类中方法进行重写
- 通过父类的引用调用重写的方法
多态体现:在代码运行时,当传递不同类对象时,会调用对应类中的方法
2.3 向上转型
子类——>父类(向上转型)
1.直接赋值:
public class Test {
public static void main(String[] args) {
/*Dog dog=new Dog("旺财",10);
Animal animal=dog;*/
Animal animal=new Dog("旺财",10);
}
}
2.方法的传参
public class Test {
public static void func(Animal animal){
}
public static void main(String[] args) {
Dog dog=new Dog("旺财",10);
func(dog);
}
}
3.返回值
public static Animal func(){
Dog dog=new Dog("旺财",10);
return dog;
}
向上转型的优点:让代码实现更加简单灵活
向上转型的缺点:不能调用到子类特有的方法
2.4 方法的重写
- 方法的名字一样
- 参数列表一样【顺序、个数、类型】
- 返回值一样
当运行代码的时候,调用了父类和子类重写的那个方法,结果实际上调用了子类的方法,这种情况叫做动态绑定。
父类引用子类对象,并且通过父类引用调用了父类和子类重写的那个对象。
注意:
- 不能是一个静态方法
- 不能是被final修饰的方法【密封方法】
- 子类重写父类的方法,那么子类的权限≥父类的权限
- 被private修饰的方法不能被重写
- 被重写的方法返回值可以不同,但必须具有父子关系
对于已经投入使用的类,尽量不要进行修改,最好的方法是:重新定义一个新的类,来重复利用其中共性的内容,并且添加或者改动新的内容。(重写)
静态绑定:也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型就确定了具体调用哪个方法,典型代表函数重载。
动态绑定:也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体调用哪个类的方法。
2.5 向下转型
public static void main(String[] args) {
Aniaml animal=new Bird("小鸟",2);
Bird bird=(Bird)animal;//强制类型转换
bird.fly();
}
向下转型有风险,不是所有的向下转型都是可以成功的。万一转型失败,运行时就会抛出异常。Java中为了提高向下转型的安全性,引入了instanceof,如果表达式为true,则可以安全转换。
2.6 多态的优缺点
使用多态的好处:
1.能够降低代码的“圈复杂度”,避免使用大量的if-else
一段代码中条件语句和循环语句出现的个数称为“圈复杂度”,如果一个方法的圈复杂度太高,需要考虑重构
2.可扩展能力强
对于类的调用者来说,只要创建一个新类的实例即可,改动成本低
多态缺陷:
代码运行效率低。
1.属性没有多态性。当父类和子类都有同名属性的时候,通过父类引用,只能引用父类自己的成员属性。
2.构造方法没有多态性
2.7 避免在构造方法中调用重写的方法
如果在父类的构造方法中调用子类和父类重写的方法,此时会发生动态绑定。
原文地址:https://blog.csdn.net/2301_80802299/article/details/140477127
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!