继承与多态

继承


设计继承时,将共同的代码放在某个类中,继承的关系意味着子类继承了父类的方法。“类的成员”成员意思就是实例变量和方法。

如果PantherMan是个SuperHero的子类,则PantherMan会自动地继承SuperHero的实例变量和方法,包括了suit、tights,specialPower、useSpecialPower()等。但PantherMan可以加入自己的方法和实例变量,也可以覆盖掉继承自SuperHero的方法。

FricdEggMan不需要任何独特的行为,所以它没有覆盖过任何的方法。然而PantherMan认为它的特殊超能力需要特别处理过的方法,所以就覆盖掉useSpecialPower0)与putOnSuit()。

实例变量无法被覆盖掉是因为不需要,它们并没有定义特殊的行为。PantherMan可以将继承下来的cights设定成紫色,而FriedEggMan可以自行选择白色。

调用哪个方法?


Wolf这个类有4个方法。其中一个继承自Animal,一个来自Canine,还有两个是自己覆盖过的。创建出一个Wolf对象并赋给它变量时,你可以使用圆点运算符来调用变量所引用对象的方法。如果类Y是继承类X,且类Y是类Z的父类,那么Z继承了X类。

12112211211

如果在子类中还打算引用父类的方法然后再加上额外的行为应该怎么办?

扩充本来就有扩充和延伸的意思.在父类中设计出所有子类都造用的功能实现。让子类可以不用完全覆盖掉父类的功能,只是再加上额外的行为。你可以道过super这个关键词来取用父类。

public void roam(){
     super.roam()
     // my own roam stuff
}
如何知道子类能够继承下来哪些东西?

子类可以继承父类的成员。包括了实例变量和方法,父类可以通过存取权限 决定子类是否能够继承某些特定的成员。左边是最受限制的,而越往右边 限制程度越小:private   default protected public。

public类型的成员会被继承

private类型的成员不会被继承

当子类把成员继承下来时会把它们当作是自己定 义的一样。例如说当某个形状体继承 Shape时, 就会有 rotate()与playSound()这两个方法。任一类的成员包含有自己定义出的变量和方法再 加上从父类所继承下来的任何东西。

要点

  • 子类是extends父类出来的。
  • 子类会继承父类所有public类型的实例变量和方法,但不会继承父类所有private类型的变量和方法。
  • 继承下来的方法可以被覆盖掉,但实例变量不能被覆盖掉。
  • 使用IS-A测试来验证继承结构的合理性。
  • IS-A关系是单方向的,河马是动物,但动物不一定是河马。
  • 当某个方法在子类中被覆盖过,调用这个方法时会调用到覆盖过的版本。
  • 如果类Y是extends类X,且类Y是类Z的父类,则Z应该能通过IS-AX的测试。
继承的意义

通过提取出一组类间共同的抽象性,能够排除掉重复的程序代码而将这个部分放在 父类中。如此一来,如果有共同的部分需要改变,就只会有一个地方要修改而已,且这样的 改变会应用到所有继承此行为的类。修改之后只需要重新编译就行,不必动子类!

多态的运行

重点在于引用类型与对象的类型必须相符。两者皆为 Dog。

Dog myDog = new Dog();

在多态下,引用与对象可以是不同的类型。

Animal myDog = new Dog();

运用多态时,引用类型可以是实际对象类型的父类,任何 extends过声明引用变量类型的对象都可以被赋值给这个引用变量。这样子你就可以做出多态数组这一类的东西。

//声明 Animal类型的数组。也就是说一个会保存Animal类型对象的数组
Animal[] animals =new Animal[5];

//放任何Animal的子类对象进去
animals[0]=new Dog();
animals [l]- new Cat();
animals[2]= new Wolf();
animals[3]= new Hippo();
animals [4]= new Lion();

//将数组的元素逐个调出来当作是Animal来操作
for(inti=0:i<animals.length;i++){
     animals[i].eat();
     animals[i].roam();
}

将参数声明成父类类型,可以在运行时传入任何的子类对象。对父类增加新类型的子类,而父类的方法依然还是能够运行。通过多态,就可以编写出引进新型子类时也不必修改的程序。

//a 参数可以用任何 Animal的类型对象来当传入。执行到makeNoise()的时候, 不
//管它引用的对象到底是什么,该对象都会执行makeNoise()

class Vet(
    public void giveshot(Animal a){
    a.makeNoise();
   }
}
覆盖的规则

参数必须要一样,且返回类型必须要兼容

父类的合约定义出其他的程序代码要如何来使用方法。不管父 类使用了哪种参数,覆盖此方法的子类也一定要使用相同的参 数。而不论父类声明的返回类型是什么,子类必须要声明返回 一样的类型或该类型的子类。要记得,子类对象得保证能够执 行父类的一切

不能降低方法的存取权限

存取权必须相同,或者更为开放。举例来说,你不能覆盖掉一个公有的方法并将它标记为私有。

方法的重载 (overload)

重载版的方法只是刚好相同名字的不同方法,它与继承或多态无关。重载的方法与覆盖方法不一 样。

1.返回类型可以不同
你可以任意地改变重载方法的返回类型,只要所有的覆盖使用不同的参数即可。
2.不能只改变返回类型
如果只有返回类型不同,但参数一样,这是不允许的。编译器不会让这样的事情过关。就算是重载,也要让返回类型是父类版返回类型的子类。重载的条件是要使用不同的参数,此时返回类型可以自由地定义。
3.可以更改存取权限
你可以任意地设定overload版method的存取权限。

public class Overloads(
    string uniqueID;
    public int addNums(int a,int b){
        return a t b;
    }

    public double addNums (double a,double b){
        return a + b;
    }

    public void setUniqueID(string theID){    
         uniqueID= theID;
    }

    public void setUniqueID(int ssNumber){
        String numstringssNumber;
        setUniqueID(numString);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值