java的覆盖实现多态_Java多态

多态

多态通过分离做什么和怎么做,从另一个角度将接口和实现分离开来

多态的作用是消除类型之间的耦合关系

多态方法调用允许一种类型表现出与其他相似类型之间的区别,只要他们都是从同一个基类导出的

Java组合与继承

组合

在新类中嵌入某个对象,让其实现所需要的功能,但是新类的用户看到的只是为新类所定义的接口

组合其实上是has-a的关系

比如一个车子,有发动机new Engine,有轮子new Wheel,有车窗new Door

继承

继承是is-a的关系

比如汽车和交通工具,不能说汽车拥有交通工具,而只能说汽车是交通工具,因此是继承关系

什么时候用组合,什么时候用继承呢

一个最清晰的判断方法就是问一问自己是否需要从新类向基类进行向上转型

如果需要向上转型,那么继承是必要的,如果不需要,应该好好考虑一下到底需不需要继承

继承的一条通用的准则是:用继承表达行为之间的差异,并用字段表达状态上面的变化

很多情况下面,更好的选择方式是组合

动态绑定

Java除了static方法和final方法,其他所有的方法都是后期绑定的。

后期绑定也叫动态绑定或者运行时绑定

通过动态绑定实现多态这个事实之后,就可以编写只与基类打交道的程序代码了。

向上转型

Shape s = new Circle()

通过继承,Circle就是一种Shaple(is-a)关系

当调用s.draw的时候,其实上调用了Circle里面的draw方法。

覆盖私有方法

public class PrivateOverride {

public void f() {

System.out.println("f in father");

}

}

public class MyOver extends PrivateOverride{

@Override

public void f() {

System.out.println("f in child");

}

public static void main(String[] args) {

PrivateOverride test = new MyOver();

test.f();

}

}

88cae21102b92c7016a64e30c555c5d9.png

仍然会调用子类的方法。

当把PrivateOverride类里面的f()改为private之后,就不是 @Override了。

因为private被自动认为是final方法,并且对导出类是屏蔽的,不可以被重载。

protected可以。

多态——向上转型“缺陷”

看下面这个代码

class Super {

public int field = 0;

public int getField() {

return field;

}

}

class Sub extends Super {

public int field = 1;

@Override

public int getField() {

return field;

}

public int getSuperField() {

return super.field;

}

}

public class FieldAccess {

public static void main(String[] args) {

Super test1 = new Sub();

System.out.println("field:" + test1.field);

System.out.println("get field:" + test1.getField());

//test1没有SuperField方法

Sub test2 = new Sub();

System.out.println("");

System.out.println("field:" + test2.field);

System.out.println("get field:" + test2.getField());

System.out.println("super field:" + test2.getSuperField());

}

}

输出结果:

ab697d569dbbeac7e76e3931f47d18d0.png

如果是Super test1 = new Sub();,那么test1是不能够有getSuperField方法的,因为受到向上转型的限制。

调用test1.field的时候,返回是0,说明返回的是基类的field

而test1.getField重载了之前的方法,所以调用test1.getField的时候,返回1,是子类的field

解决办法:

通常会将所有的域这只为private

基类中的域和导出类中的域一般不可能会赋予相同的名字,这样的做法很容易令人混淆

private方法、static方法、final方法都不具有多态性

构造器和多态

class Meal {

Meal() {

System.out.println("Meal()");

}

}

class Bread {

Bread() {

System.out.println("Bread()");

}

}

class Lunch extends Meal {

Lunch() {

System.out.println("Lunch()");

}

}

class ProtableLunch extends Lunch {

ProtableLunch() {

System.out.println("ProtableLunch()");

}

}

public class Sandwich extends ProtableLunch{

Bread bread = new Bread();

Sandwich() {

System.out.println("Sandwich()");

}

public static void main(String[] args) {

Sandwich sandwich = new Sandwich();

}

}

13d3ad7b637db0fc95915d1736dacdb6.png

从输出可以看到:

首先调用基类构造器,这个步骤会反复递归下去

按照声明的孙旭调用成员的初始化方法

调用导出类构造器主体

构造器的调用顺序是很重要的。当进行继承时,我们已经知道基类的一切,并且可以访问基类中任何声明为public和protected的成员。

标签:Java,System,多态,field,println,new,public,out

来源: https://blog.csdn.net/weixin_36372879/article/details/101224558

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值