【问题标题】:How to replace if/else with polymorphism in a class?如何用类中的多态性替换 if/else?
【发布时间】:2021-03-09 11:23:23
【问题描述】:

我一直在阅读有关多态性的内容,并且对一个 java 示例非常感兴趣,该示例用抽象类替换了长 switch 语句,该抽象类自动选择正确的子类来执行请求的操作。

例如:

// switch version
class Bird {
  // ...
  getSpeed(): number {
    switch (type) {
      case EUROPEAN:
        return getBaseSpeed();
      case AFRICAN:
        return getBaseSpeed() - getLoadFactor() * numberOfCoconuts;
      case NORWEGIAN_BLUE:
        return (isNailed) ? 0 : getBaseSpeed(voltage);
    }
    throw new Error("Should be unreachable");
  }
}

// polymorphism version
abstract class Bird {
  // ...
  abstract getSpeed(): number;
}

class European extends Bird {
  getSpeed(): number {
    return getBaseSpeed();
  }
}
class African extends Bird {
  getSpeed(): number {
    return getBaseSpeed() - getLoadFactor() * numberOfCoconuts;
  }
}
class NorwegianBlue extends Bird {
  getSpeed(): number {
    return (isNailed) ? 0 : getBaseSpeed(voltage);
  }
}

// Somewhere in client code
let speed = bird.getSpeed();

避免嵌套在类函数中的长 if/else 语句(我知道我可以将此代码封装在不同的函数中以获得更高的可读性,但最终我仍然需要处理许多 if/else)并自动切换到正确的子类会很棒!

如何在Javascript中做到这一点?

我写了类似的东西:

// base
class Bird {
  constructor(name){
    this.name = name
  }
  greets() {
    switch (this.name) {
      case "gull":
        return console.log("it's a gull")
      case "sparrow":
        return console.log("it's a sparrow")
      case "dove":
        return console.log("it's a dove")
    }
  }
} 

const bird = new Bird("sparrow")
bird.greets()
// output: "it's a sparrow"

// my poor attempt:
class Bird {
  constructor(name){
    this.name = name
  }
  greets() { 
      throw new Error("not implemented"); 
  }
}

class Gull extends Bird {
  greets(){
    return console.log("it's a gull")
  }
}

class Sparrow extends Bird {
  greets(){
    return console.log("it's a sparrow")
  }
}

class Dove extends Bird {
  greets(){
    return console.log("it's a dove")
  }
}

const bird = new Bird("gull")
bird.greets()
// output: Uncaught SyntaxError: Unexpected token '}' 

如何用这个简单的鸟类实现多态性?我当然应该为 Dove、Sparrow 和 Gull 扩展 Birds,但我只想在代码中调用 Bird 控制器,因为我不知道最终会得到哪种鸟。

谢谢!

ps:如果有更简单的方法可以通过函数实现这一点,我也很高兴收到您的来信!

【问题讨论】:

    标签: javascript polymorphism


    【解决方案1】:

    非常接近你提供的例子(一个例子):

    class Bird {
      // ...
      getSpeed() { 
          throw new Error("not implemented"); 
      }
    }
    
    class European extends Bird {
      getSpeed() {
        return 15;
      }
    }
    class African extends Bird {
      getSpeed() {
        return 17;
      }
    }
    class NorwegianBlue extends Bird {
      getSpeed() {
        return (isNailed) ? 0 : 10;
      }
    }
    
    // Somewhere in client code - bird is an instance one of the classes that extends Bird
    let speed = bird.getSpeed();
    

    或者,如果你想使用更接近你发布的语法,你可以使用Typescript

    【讨论】:

    • 我遵循了打字稿示例,但我不能使用 Bird 类。看来我总是不得不使用 Gull、Sparrow 或 Dove。但整个想法是只使用 Bird 并让它决定调用哪个类。我在这里做了一个沙盒:codesandbox.io/s/amazing-bush-owmt6?file=/src/Bird.ts
    • @DoneDeal0 那是因为您正在调用 (inApp.tsx):const bird = new Bird("gull");Bird 是一个抽象类 - 您不能创建抽象类的实例!我们应该做的是:const bird = new Gull();
    • 是的,但这违背了我的目标。我知道如何实例化类和子类,但我想要的是允许自动切换到子类以定义特定的子方法。例如,我收到一只鸟,我想描述它,但根据鸟的不同,描述功能可能会有很大不同。目前,我有一个带有许多 if/else 语句的 greet 函数。这里我不能调用具体的子类,因为我不知道我会收到哪种鸟。
    • @DoneDeal0 这正是你能够做到的,所以我看不出它如何违背你的目标。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-05
    • 1970-01-01
    • 2014-11-29
    • 2017-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多