面向对象编程的组合、多态、抽象类的基本介绍(一)

简介: 面向对象编程的组合、多态、抽象类的基本介绍

面向对象

组合

和继承类似,组合也是表达类之家关系的方式,也是能够达到代码冲用的效果

例如:

组合并没有涉及到特殊的语法(诸如extends关键字),仅仅是将一个类的实例作为另一个类的字段,这是我们设计类的一种常用的方式之一

组合表示is-a语义

在刚才的例子中我们可以理解成一个学校“包含”若干学生和教师

继承表示has-a语义

在上面的“动物和猫”的例子中,也可以理解成猫也“是”一种动物

多态

向上转型

在上篇文章当中我们写了如下的代码

Bird bird = new Bird("圆圆");

这个代码也可以写成这样子

Animal bird2 = new Bird("圆圆");

此时bird2是一个父类(Animal)的引用,指向了一个子类(Bird)的实例,这种写法为向上转型

为啥叫“向上转型”?

在面向对象程序设计中,针对一些复杂的场景(很多类,很复杂的继承关系),程序员会画一种UML图来表示类之间的关系,此时父类通常画在子类的上方,我们就称之为“向上转型”,表示往父类的方向转,

注意:关于UML图的的规则我们不详细讨论,有兴趣的伙伴可以自己看看

向上转型发生的时机:

  • 直接赋值
  • 方法传参
  • 方法返回
    直接赋值的方式就是如上所示,另外两种方式和直接赋值没有本质区别

方法传参

public class Test {
  public static void feed(Animal animal){
    animal.eat("谷子");
  }
  public static void main(String[] args) {
    Bird bird = new Bird("圆圆");
    feed(bird);
  }
}
//执行结果
//圆圆正在吃谷子

此时形参animal的类型是Animal(基类),实际上对应到Bird(父类)的实例

方法返回

public class Test { 
  public static void main(String[] args) { 
    Animal animal = findMyAnimal(); 
  } 
  public static Animal findMyAnimal() { 
    Bird bird = new Bird("圆圆"); 
    return bird; 
  } 
}

此时findMyAnimal返回的是一个Animal类型的的引用,但是实际上对应到Bird的实例

动态绑定

当子类和父类中出现同名方法的时候,再去调用会出现什么情况?

class Animal {
    String name;
    public Animal(String name) {
        this.name = name;
    }
    public void eat(String food) {
        System.out.println("我是一只小动物");
        System.out.println(this.name + "正在吃" + food);
    }
}
class Bird extends Animal {
    public Bird(String name) {
        super(name);
    }
    public void eat(String food) {
        System.out.println("我是一只小鸟");
        System.out.println(this.name + "正在吃" + food);
    }
}
public class Main {
    public static void main(String[] args) {
        Animal animal = new Animal("圆圆");
        animal.eat("谷子");
        Animal animal2 = new Bird("扁扁");
        animal2.eat("谷子");
    }
}

运行结果:

此时我们发现:

  • animal1animal2虽然都是Animal类型的引用,但是animal1指向了Animal类型的实例,animal2指向了Bird类型的实例
  • 针对animal1animal2分别调用了eat方法,发现animal1.eat实际调用了父类的方法,而animal2.eat实际调用了子类的方法

方法重写

针对刚才的eat方法来说

子类实现父类的同名方法,并且参数的类型和个数完全相同,这种情况成为覆写/重写/覆盖(Override)

关于重写的注意事项

1.重写和重载完全不一样,不要混淆

2.普通的方法也可以重写,static修饰的静态方法不能重写

3.重写中子类的方法的访问权限不能低于父类的方法访问权限

4.重写的方法返回值类型不一定和父类的方法相同(但是建议写成相同,特殊情况除外)

有了这个注解能帮助我们进行一些合法性校验,例如不小心将名字拼错了(比如写成aet),那么此时编译器就会发现父类中没有aet方法,就会编译错误显示无法构成重写

小结:重载和重写的区别

体会动态绑定和方法重写

上面的动态绑定和方法重写使用的相同的代码示例

事实上,方法重写是Java语法层次上的规则,而动态绑定是方法重写这个语法规则的底层实现,两者本质上描述的是相同的事情,只是侧重点不同


相关文章
|
Java
面向对象编程的三大特征:封装;继承;多态
面向对象编程的三大特征:封装;继承;多态
66 0
|
3月前
|
Java 编译器
封装,继承,多态【Java面向对象知识回顾①】
本文回顾了Java面向对象编程的三大特性:封装、继承和多态。封装通过将数据和方法结合在类中并隐藏实现细节来保护对象状态,继承允许新类扩展现有类的功能,而多态则允许对象在不同情况下表现出不同的行为,这些特性共同提高了代码的复用性、扩展性和灵活性。
封装,继承,多态【Java面向对象知识回顾①】
|
6月前
|
Python
面向对象详解,面向对象的三大特征:封装、继承、多态-1
面向对象详解,面向对象的三大特征:封装、继承、多态
|
6月前
|
Python 容器
面向对象详解,面向对象的三大特征:封装、继承、多态-2
面向对象详解,面向对象的三大特征:封装、继承、多态
|
7月前
|
Java
面向对象——多态,抽象类,接口(二)-2
面向对象——多态,抽象类,接口(二)
31 1
|
7月前
|
安全 Java 程序员
面向对象——多态,抽象类,接口(二)-1
面向对象——多态,抽象类,接口(二)
44 1
|
6月前
|
安全
面向对象特征(抽象、封装、继承、多态)的具体用法
面向对象特征(抽象、封装、继承、多态)的具体用法
24 0
|
7月前
|
编译器 C++
[C++] 面向对象的三大特性:封装、继承和多态
[C++] 面向对象的三大特性:封装、继承和多态
83 0
|
设计模式 数据安全/隐私保护
面向对象编程基础:封装、继承、多态与抽象的全面解析
面向对象编程基础:封装、继承、多态与抽象的全面解析
221 0
浅谈 面向对象三大特性:封装 继承 多态
浅谈 面向对象三大特性:封装 继承 多态
91 0