加入收藏 | 设为首页 | 会员中心 | 我要投稿 安卓应用网 (https://www.0791zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

Java编程―在测试中考虑多态

发布时间:2020-05-23 14:32:35 所属栏目:Java 来源:互联网
导读:面向对象编程有三大特性:封装、继承、多态。封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据。对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法。

面向对象编程有三大特性:封装、继承、多态。

封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据。对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法。

继承是为了重用父类代码。两个类若存在IS-A的关系就可以使用继承。,同时继承也为实现多态做了铺垫。那么什么是多态呢?多态的实现机制又是什么?请看我一一为你揭开:

所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。练习(1):创建一个Cycle类,它具有子类Unicycle,Bycycle,Tricycle.演示每一个类型的实例都可以经由ride()方法向上转型为Cycle.

向上转型就是允许将多种从同一基类的导出类看成同一类型。

多态方法调用就是允许一种类型表现出与其他相似类型之间的区别,只要他们是从同一基类导出而来的。这种区别由各个导出类型方法的具体不同实现而表现出来的,虽然这些方法都是由基类调用的。

public class Test1 {
  public static void main(String[] args){
    Unicycle unicycle = new Unicycle("Unicycle");
    Bicycle bicycle = new Bicycle("Bicycle");
    Tricycle tricycle = new Tricycle("Tricycle");
    Cycle.ride(unicycle);
    Cycle.ride(bicycle);
    Cycle.ride(tricycle);
  }
}
class Cycle{
  private String name;
  public Cycle(String str){
    name = str;
  }
  public static void ride(Cycle c){
    System.out.println(c.name + "is riding");
  }
}
class Unicycle extends Cycle{
  private String name;
  public Unicycle(String str) {
    super(str);
    name = str;
  }
}
class Bicycle extends Cycle{
  private String name;
  public Bicycle(String str) {
    super(str);
    name = str;
  }
}
class Tricycle extends Cycle {
  private String name;
  public Tricycle(String str) {
    super(str);
    name = str;
  }
}

输出:

Unicycleis riding

Bicycleis riding

Tricycleis riding

在以上示例中,三种子类能被视作Cycle传入到方法ride()中就是向上转型。

但向上转型只是看成,而不是强制转换,所以最后方法调用的结果不同,这就是多态。

多态又称之为动态绑定。什么是动态绑定?

与动态绑定相反的是静态绑定。c语言所有方法都是默认静态绑定。静态绑定也称为前期绑定,就是在程序运行前就绑定完成。也就是说,代码写了什么样,就是什么样。

而动态绑定是直到运行时才去决定该方法调用该绑定哪个实体。

java中的所有static和final方法都是静态绑定,其他的所有方法都是动态绑定。

练习(2):在几何图形示例中添加@Override注解。

练习(3):在基类Shape.java中添加一个新方法,用于打印一条消息,但导出类中不要覆盖这个方法。请解释发生了什么。现在,在其中一个导出类中覆盖该方法,而在其他的导出类中不予覆盖,观察又有什么发生。最后,在所有的导出类中覆盖这个方法。

练习(4):向Shapes.java中添加一个新的Shape类型,并在main()方法中验证:多态对新类型的作用是否与在旧类型中的一样。

以上三个练习在一份示例中完成。

public class Test234 {
  private static RandonShapeGenerator gen = new RandonShapeGenerator();
  public static void main(String[] args){
    Shape[] shapes = new Shape[9];
    for (int i = 0; i < shapes.length; i++) {
      shapes[i] = gen.next();
    }
    for (Shape s :
        shapes) {
      s.draw();
      s.newMethod();//每个子类都调用了一次添加的新方法,
      // 因为子类继承父类自然把所有方法都继承过去了,只不过没有显示出来,
      // 其实是隐式的存在的,子类调用的其实是继承自父类的没有重写的方法,
      // 看起来像是调用了父类的方法
    }
    Shape s = new Recf();//这里是声明了一个Shape类型的引用,但实际的对象还是Recf.
    s.draw();//输出的是Recf类重写的方法,证明多态对新类的作用于在旧类中是一样的
  }
}
class Shape{//基类
  public void draw(){}
  public void erase(){}
  public void newMethod(){
    System.out.println("new method");//添加的新方法
  }
}
class Circle extends Shape{
  @Override//添加注解,一般IDE可以自动添加
  public void draw() {
    System.out.println("draw circle");
  }
  @Override
  public void erase() {
    System.out.println("erase circle");
  }
}
class Square extends Shape{
  @Override
  public void draw() {
    System.out.println("draw Square");
  }
  @Override
  public void erase() {
    System.out.println("erase Square");
  }
  @Override
  public void newMethod() {
    System.out.println("Square new method");
    //重写后该类输出内容就发生改变,没有重写时该类的该方法与父类运行结果相同
    //无论重写与否,其实调用的都是自身的方法
    //只是没有重写时方法调用结果与父类的相同
  }
}
class Triangle extends Shape{
  @Override
  public void draw() {
    System.out.println("draw Triangle");
  }
  @Override
  public void erase() {
    System.out.println("erase Triangle");
  }
}
class Recf extends Shape{//新添加的方法
  @Override
  public void draw() {
    System.out.println("recf draw");
  }
  @Override
  public void erase() {
    System.out.println("recf erase");
  }
}
class RandonShapeGenerator{//是一种工厂,用以随机获取一种Shape的子类
  private Random rand = new Random(100);
  public Shape next(){
    switch (rand.nextInt(3)){
      default:
      case 0:return new Circle();
      case 1:return new Square();
      case 2:return new Triangle();
    }
  }
}

练习(5):以练习1为基础,才Cycle中添加wheels()方法,它将返回轮子的数量。修改ride()方法,让它调用wheels()方法,并验证多态起作用了。

在练习(1)的代码中给基类添加

public void wheels(){
    System.out.println("轮子数量是" + num);
  }

然后在main中:

unicycle.wheels();
bicycle.wheels();
tricycle.wheels();

最后输出结果都顺利输出了方法中的语句,证明多态确实起作用了。

练习(6):修改Music3.java,是what()方法成为根Object的toString()方法。试用System.out.pringtln()方法打印Instrument对象(不用向上转型).

练习(7):向Music3.java添加一个新的类型Instrument,并验证多态性是否作用于所添加的新类型.

练习(8):修改Music3.java,使其可以向Shapes.java中的方式那样随机创建Instrument对象。

三个练习将在一份代码完成。

public class Test678 {
  public static void main(String[] args){
    Instrument[] orchestar = {
        new Wind(),new Percussion(),new Stringed(),new Brass(),new Woodwing()
    };
    tuneAll(orchestar);
    newInstrument ni = new newInstrument();
    ni.play(Note.B_FLAT);//验证多态性是否适用于所添加的新类型,答案是确实适用。
  }
  public static void tune(Instrument instrument){
    instrument.play(Note.MIDDLE_C);//无论传进声明子类,都播放MIDDLE_C
  }
  public static void tuneAll(Instrument[] e){
    for (Instrument i :
        e) {
      tune(i);
      System.out.println(i.toString());
    }
  }
}
class RandomInsFactory{//工厂类,用于随机生成一个Instrument的子类
  private Random ran = new Random(47);
  public Instrument next(){
    switch (ran.nextInt(5)){
      default:
      case 0:return new Wind();
      case 1:return new Percussion();
      case 2:return new Stringed();
      case 3:return new Brass();
      case 4:return new Woodwing();
      case 5:return new newInstrument();
    }
  }
}
enum Note{//枚举类,存放了哪些音乐
  MIDDLE_C,C_HARPE,B_FLAT;
}
class Instrument {
  void play(Note note){
    System.out.println("Instrument.play() : " + note);
  }
  String what(){
    return "Instrument";
  }
  void adjust(){
    System.out.println("adjusting Instrument");
  }
  @Override
  public String toString() {
    // /添加一个toString方法,调用当前what方法,
    // 子类会自动继承该方法并分别返回给自what()里的内容
    return what();
  }
}
class Wind extends Instrument{
  @Override
  void play(Note note) {
    System.out.println("Wind.play() : " + note);
  }
  @Override
  String what() {
    return "Wind";
  }
  @Override
  void adjust() {
    System.out.println("adjusting Wind");
  }
}
class Percussion extends Instrument{
  @Override
  void play(Note note) {
    System.out.println("Percussion.play() : " + note);
  }
  @Override
  String what() {
    return "Percussion";
  }
  @Override
  void adjust() {
    System.out.println("adjusting Percussion");
  }
}
class Stringed extends Instrument{
  @Override
  void play(Note note) {
    System.out.println("Stringed.play() : " + note);
  }
  @Override
  String what() {
    return "Stringed";
  }
  @Override
  void adjust() {
    System.out.println("adjusting Stringed");
  }
}
class Brass extends Wind{//继承自Wind
  @Override
  void play(Note note) {
    System.out.println("Brass.play() : " + note);
  }
  @Override
  void adjust() {
    System.out.println("adjusting Brass");
  }
}
class Woodwing extends Wind{
  @Override
  void play(Note note) {
    System.out.println("Woodwing.play() : " + note);
  }
  @Override
  String what() {
    return "Woodwing";
  }
}
class newInstrument extends Instrument{//新添加的类型
  @Override
  void play(Note note) {
    System.out.println("newIns.play()" + note);
  }
}

(编辑:安卓应用网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读