静态绑定
重载就是典型例子
动态绑定
多态的具体实现
//多态 class Animal{ public String name; public int age; //无参构造方法 public Animal() { } //有参构造方法 public Animal(String name,int age) { this.name = name; this.age = age; } //成员方法 public void eat(){ System.out.println(this.name+"正在吃饭"); } } class Dog extends Animal { //子类构造完成之前要帮助父类构造完成 public Dog(String name, int age) { super(name, age); } //重写eat方法 public void eat() { System.out.println(this.name + "正在吃狗粮"); } } class Cat extends Animal { //子类构造完成之前要帮助父类构造完成 public Cat(String name, int age) { super(name, age); } //重写eat方法 public void eat() { System.out.println(this.name + "正在吃猫粮"); } } public class Test { //多态的第一种 public static void func(Animal animal){ animal.eat();//向上转型中的方法传参 } public static void main(String[] args) { Dog dog = new Dog("红红",12); func(dog); Cat cat = new Cat("青青",13); func(cat); } //多态的第二种 public static void main2(String[] args) { Animal animal = new Dog("红红",12);//向上转型中的直接赋值 animal.eat(); Animal animal2 = new Cat("青青",13); animal2.eat(); } }
向上转型
语法格式:父类类型 对象名 = new 子类类型()
animal是父类类型,但可以引用一个子类对象,因为是从小范围向大范围的转换。
【使用场景】
例如上面的代码中
- 直接赋值
例如上面的代码
Animal animal = new Dog("红红",12);
- 方法传参
例如上面的代码
public static void func(Animal animal){ animal.eat(); }
- 方法返回
// 作返回值:返回任意子类对象 public static Animal buyAnimal(String var){ if("狗".equals(var) ){ return new Dog("狗狗",1); }else if("猫" .equals(var)){ return new Cat("猫猫", 1); }else{ return null; } }
总结:
向上转型的优点:让代码实现更简单灵活。
向上转型的缺陷:不能调用到子类特有的方法
多态的优缺点
【使用多态的好处】
- 能够降低代码的 “圈复杂度”, 避免使用大量的 if - else
- 可扩展能力更强
如果要新增一种新的形状, 使用多态的方式代码改动成本也比较低
【多态缺陷】
3. 代码的运行效率降低。
4. 属性没有多态性
当父类和子类都有同名属性的时候,通过父类引用,只能引用父类自己的成员属性
5. 构造方法没有多态性
【避免在构造方法中调用重写的方法】
尽量不要在构造器中调用方法(如果这个方法被子类重写, 就会触
发动态绑定, 但是此时子类对象还没构造完成), 可能会出现一些隐藏的但是又极难发现的问题。
抽象类
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类
1.被abstract修饰的类叫做抽象类
2.被abstract修饰的方法叫做抽象方法
3.抽象类不可以实例化
4.当一个普通类继承了抽象类,那么需要重写这个抽象类中的所有抽象方法!!
abstract class Shape{ public abstract void draw(); } class Cycle extends Shape{ @Override public void draw() { System.out.println("⚪"); } }
如果不继承 ,子类也是抽象类,必须要使用 abstract 修饰
abstract class C{ public abstract void draw(); } abstract class A extends C { abstract public void run(); } class B extends A{ @Override public void draw() { } @Override public void run() { } }
总结:抽象类的出现就是为了被继承
abstract class Shape{ public abstract void draw(); } class Cycle extends Shape{ //重写抽象类的抽象方法 @Override public void draw() { System.out.println("⚪"); } }class Rect extends Shape{ //重写抽象类的抽象方法 @Override public void draw() { System.out.println("矩形"); } } public class Test { public static void func(Shape shape){ shape.draw(); } public static void main(String[] args) { Shape shape =new Cycle(); Shape shape2 =new Rect(); shape.draw(); shape2.draw(); } }
7.abstract 和final 是天敌,不能共存
8.private 、static 也不可以修饰 抽象方法
抽象类的作用
抽象类不能被实例化,要想使用,必须要实现该抽象类的子类,然后在子类中重写抽象类的抽象方法。
抽象类的作用就是一个检验作用。
子类继承父类,子类中是需要重写父类方法的,但如果不小心误用成父类了,编译器不会报错,所以,父类是抽象类的话,当子类没有重写,编译器会主动报错噢。
总结
继承多态之间涉及到的子类构造方法,向上转型,动态绑定,以及抽象类和继承的关系等等知识还是挺复杂的,多写写代码思路会清晰些。