【问题标题】:Can I change return type of method in extended class?我可以更改扩展类中方法的返回类型吗?
【发布时间】:2019-10-21 16:08:53
【问题描述】:

我需要类B扩展接口C,但是我想使用A::methodA的实现来计算B::methodA的结果。


interface C {
  methodA(): number
}

class A {
  methodA(): string {
    return '42'
  }
}

class B extends A implements C {
  methodA(): string {
    return Number(super.methodA()).
  }
}

我可以将A 类的实现与继承一起使用,还是关联是我唯一的希望?

【问题讨论】:

  • 您能否让这些名称就您实际需要做的事情而言有点明显?因为如前所述,没有真正的理由这样做:methodA 通常会有一个名称,如果正确选择,已经暗示结果将是一个字符串并且有一个子类也试图实现冲突的界面真的很奇怪。
  • 尝试进行继承将是painful and messy。对于这样的事情,继承是脆弱的;人们建议使用作曲是有原因的。

标签: javascript typescript clean-architecture


【解决方案1】:

你可以让 A 类中的 methodA 返回类型为 any 而不是字符串。

interface C {
   methodA(): number
}

class A {
  protected methodA(): any {
    return '42'
  }
}

class B extends A  implements C {
    methodA(): number {
      return Number(super.methodA());
  }
}

【讨论】:

    【解决方案2】:

    您可以在接口Cnumber | string, 上定义方法A() 的返回类型,它必须是兼容的返回类型。

    interface C {
      methodA(): number | string
    }
    
    class A {
      methodA(): string {
        return '42'
      }
    }
    
    class B extends A implements C {
      methodA(): string {
        return super.methodA();
      }
    }
    

    编辑:所以考虑到下面的场景,它可能不是最好的解决方案,但您可以使用实用程序类型 Omit 并从 C 创建一个新类型,以避免验证 method1(更多示例 @987654322 @)

    interface C {
      methodA(): number
      //methodB(): string,
      //methodC(): number
      //..
    }
    type C1 = Omit<C, "methodA">;
    
    class A {
      methodA(): string {
        return '42'
      }
    }
    
    class B extends A implements C1 {
      methodA(): string {
        return super.methodA();
      }
    }
    

    【讨论】:

    • 很好的建议,但它不会起作用。接口C 实际上是从域中导入的。我的AB 类实际上使用了更复杂的类型……目前我正在B 类中从一种类型映射到另一种类型。不幸的是,如果我想使用干净的架构,我无法从外部将任何内容导入域
    • 您可以尝试使用 Omit 实用程序类型
    【解决方案3】:

    在使用 OO 构造(例如继承)开发软件时,您应该注意SOLID principles。这些原则旨在使您的代码更易于理解、灵活和可维护。它们被广泛认为是最佳实践。

    因此,虽然您可以使用先前答案建议的解决方法(例如联合类型)来允许在被覆盖的方法中使用不同的返回类型...您应该考虑这是否会产生清晰、可维护的代码。

    尤其是,这样做可能会违反 Liskov 替换原则,该原则指出:

    “程序中的对象应该可以替换为其子类型的实例,而不会改变该程序的正确性。”

    【讨论】:

      【解决方案4】:

      在 JavaScript 中,我们可能谈论的是对象而不是类之间的继承, 这是您使用原型的示例的简单实现

      class A {
          constructor (){}
          methodA() {
              return '42'
          }
      }
      
      class B extends A{
          constructor (){
              super();
          } 
          methodA(){};
      }
      
      b = new B();
      a = new A();
      
      B.prototype.methodA = function (nbr){ return 1 * nbr};
      console.log("B " + b.methodA('4'))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-11-15
        • 1970-01-01
        • 1970-01-01
        • 2011-07-16
        • 1970-01-01
        • 2014-09-08
        • 1970-01-01
        相关资源
        最近更新 更多