java多态怎么学_Java多态的学习

首先,我要说明的是,继承、封装、多态并不是针对JAVA,c#或者其他某种语言产生的,它是面向对象思想下产生的一个概念。

让我自己说的话,我只能用三句话来描述(不知道对不对,请高手指点):

* 继承:使得子类继承父类的属性和方法,也可以使用父类的功能。

* 封装:将具体实现隐藏,只留给用户使用的接口。

* 多态:相似类型在使用同一基类方法时,可以表现出与基类不同的行为。

一直记不住这些概念,百度了下,放在这供参考:

1、继承(inheritance)     继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。这种技术使得复用以前的代码非常容易,能够大大缩短开发周期,降低开发费用。

继承是为了重用父类代码,同时为实现多态性作准备。

2、封装(encapsulation)     类使得数据和对数据的操作集成在一起,从而对使用该类的其他人来说,可以不管它的实现方法,而只管用它的功能,从而实现所谓的信息隐藏。  封装隐藏了类的内部实现机制,从而可以在不影响使用者的前提下改变类的内部结构,同时保护了数据。

3、多态(polymorphism)

方法的重写、重载与动态连接构成多态性。Java之所以引入多态的概念,原因之一是它在类的继承问题上和C++不同,后者允许多继承,这确实给其带来的非常强大的功能,但是复杂的继承关系也给C++开发者带来了更大的麻烦,为了规避风险,Java只允许单继承,派生类与基类间有IS-A的关系(即“猫”is a “动物”)。这样做虽然保证了继承关系的简单明了,但是势必在功能上有很大的限制,所以,Java引入了多态性的概念以弥补这点的不足,此外,抽象类和接口也是解决单继承规定限制的重要手段。同时,多态也是面向对象编程的精髓所在。     多态又分为设计时多态和运行时多态,例如重载又被称为设计时多态,而对于覆盖或继承的方法,JAVA运行时系统根据调用该方法的实例的类型来决定选择调用哪个方法则被称为运行时多态。总而言之,面向对象的设计的典型特点就是继承,封装和多态,这些特点也是面向对象之所以能如此盛行的关键所在。

对于多态,可以总结它为:

一、使用父类类型的引用指向子类的对象;该引用只能调用父类中定义的方法和变量;

二、如果子类中重写了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法;(动态连接、动态调用)

三、变量不能被重写(覆盖),”重写“的概念只针对方法。

对多态的理解:

个人觉得多态是最为抽象的一个概念,那就用实例来解释了。

1. public, protected的方法具有多态性,但是如果某个方法是静态的,就不具有多态性,因为静态方法是与类而非单个对象相关联的。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagecom.wx.test;public classBase {public voidpublicMethod() {

System.out.println("Base public Method");

}protected voidprotectedMethod() {

System.out.println("Base protected Method");

}public static voidpublicStaticMethod() {

System.out.println("Base protected Method");

}

}public class Sub1 extendsBase {public voidpublicMethod() {

System.out.println("Sub1 public Method");

}protected voidprotectedMethod() {

System.out.println("Sub1 protected Method");

}public static voidpublicStaticMethod() {

System.out.println("Sub1 protected Method");

}

}public class Sub2 extendsBase {public voidpublicMethod() {

System.out.println("Sub2 public Method");

}protected voidprotectedMethod() {

System.out.println("Sub2 protected Method");

}public static voidpublicStaticMethod() {

System.out.println("Sub2 protected Method");

}

}public classTest {public static voidmain(String[] args) {

Base base1= newSub1();

Base base2= newSub2();

base1.publicMethod();

base2.publicMethod();

base1.protectedMethod();

base2.protectedMethod();

base1.publicStaticMethod();

base2.publicStaticMethod();

}

}

View Code

运行结果如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

Sub1 publicMethod

Sub2publicMethod

Sub1protectedMethod

Sub2protectedMethod

BaseprotectedMethod

Baseprotected Method

View Code

从以上结果可以看到,将子类对象转换成父类对象,对于public和protected方法调用时,是调用了实际创建的子类方法。问题就在于编译器只有一个父类对象,它无法知道调用哪个方法才对。这个问题解决办法就是后期绑定,就是编译器确实不知道调用哪个方法,运行时才根据对象类型进行绑定,从而调用子类方法。也就是编译器一直不知道对象类型,方法调用机制可以知道类型信息,从而找到正确的方法体。

2.“覆盖”私有方法

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagecom.wx.test;public classSuper {private voidfunction()

{

System.out.println("Super private Method");

}public static voidmain(String[] args) {

Super sup= newSub();

sup.function();

}

}public class Sub extendsSuper{public voidfunction()

{

System.out.println("Sub public Method");

}

}

View Code

运行结果如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

Super private Method

View Code

我们期望输出Sub public Method,但是由于private方法被自动认为是final方法而且对于子类是不可见的,因此Sub中的function()是一个新的方法。所以私有方法是不能被覆盖的。

3. 属性不可以是多态的

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagecom.wx.test;public classSuper {public int field = 0;public int getField() { returnfield; }

}public class Sub extendsSuper{public int field = 1;public int getField() { returnfield; }

}public classTest {public static voidmain(String[] args) {

Super sup= newSub();

Sub sub= newSub();

System.out.println("sup.field = "+ sup.field +"," + "sup.getField() = " +sup.getField());

System.out.println("sub.field = "+ sub.field +"," + "sub.getField() = " +sub.getField());

}

}

View Code

运行结果如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

sup.field = 0,sup.getField() = 1sub.field= 1,sub.getField() = 1

View Code

不过在实践中这种情况一般不会发生,一是属性会被定义为private,因此不能直接访问,二是子类不会定义和基类相同名字的属性,这种做法容易混淆。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值