【问题标题】:instanceof child causing circular dependencyinstanceof child 导致循环依赖
【发布时间】:2018-01-06 01:58:47
【问题描述】:

有没有办法检查某物是否是没有importing 的对象的实例?

我使用的班级instanceof 是当前班级的孩子。我有一个方法可以运行一个函数并根据一些 if 语句返回一个 ModelRow 的新实例。 Model 扩展了具有我正在使用instanceof 的方法的类,我想检查它是否是Model 的实例,然后做一些额外的操作。

export class Base {
    public firstOrFail() {
        let val = this.first() // Returns a new instance of Model or Row
        if(val instanceof Model && val.length == 0) {
            throw new Error('No values')
        }
    }
}

然后我有两个文件,每个看起来像这样:

// File Model.ts
import { Base } from './Base'
export class Model extends Base {}

// File Row.ts
export class Row {}

我遇到的问题是,如果我在 base 中导入 Model,我会得到一个循环依赖循环。如果我不需要它,我会收到一个错误:

找不到名称“模型”

那么有没有办法我可以在 Base 类中做 instanceof

有两种使用方式:

new Base().firstOrFail()

new Model().firstOrFail()

【问题讨论】:

  • 导入模型。它就在文件模型中
  • 在那里使用instanceof Model的目的是什么?为什么需要它?
  • 因为Base 也需要访问firstOrFail 方法。首先将返回一个Row | Model 的实例,如果Model 的内部数组的长度为零,它应该抛出一个错误,也就是“失败”。但是行,没有内部数组,所以不需要在那里检查
  • 目前我正在使用 if ('length' in val && val.length == 0) 这在 JavaScript 中有效,但打字稿抱怨它。 Property 'length' does not exist on type 'this | Row<I>'(这是模型)这是一个错误顺便说一句:github.com/Microsoft/TypeScript/issues/20893
  • 因此,基类需要了解派生类的任何信息通常被认为是不好的形式。这里更好的答案是修复你的逻辑和结构,这样就根本不需要发生。

标签: javascript node.js typescript


【解决方案1】:

那么有什么方法可以在 Base 类中执行 instanceof 吗?

除非将它们放在同一个文件中,否则不容易。 instanceof 要求您在使用之前定义要测试的对象。您可以使用一些技巧将它们保存在单独的文件中,因为当定义 Base 对象时,您实际上不需要对 Model 类的引用(仅在 Base 对象时才需要已实例化),但我建议修复设计而不是追求这个。

基类需要了解派生类的任何信息通常被认为是糟糕的 OO 形式。任何特定于派生类的行为都应该在派生类中实现,而基类总是可以帮助派生类通过适当的设计完成他们需要做的事情。在 20 年的 OO 设计中,我从未找到一个正当理由让基类必须了解派生类的任何信息。

因此,这里的更好答案将是修复您的逻辑和结构,以便您的 Base 类不需要了解有关 Model 类的任何信息。

您可以使用的一种实现方式是在 Model 类中覆盖 firstOrFail()。您可以将其转换为 typescript,但这就是它在普通 ol' ES6 中的样子:

// Base.js
export class Base {
    firstOrFail() {
        // common, shared implementation
        // derived classes may override to provide validation
        return this.first();
    }
}

// Model.js
import { Base } from './Base'

class Model extends Base {
    constructor() {
       super();
    }
    firstOrFail() {
        let val = super.firstOrFail();
        if (val.length == 0) {
            throw new Error('No values')
        }
        return val;
    }
}

【讨论】:

  • 完美!我刚刚意识到我已经在做其中的一部分了:),所以现在我只需要将那部分逻辑移到模型中
  • 如果您想要在父类中创建一个由不同类型的派生类实例组成的数组的方法,您会使用哪种模式?我确定我做错了什么,但我不知道如何在不创建循环依赖的情况下解决这个问题。
  • @joshhunt - 我们必须更多地了解您实际想要完成的工作。我建议您编写自己的问题,描述实际的设计问题以及为什么要在基类中使用该数组,然后我们也许可以提出更好的设计。简短的回答是不要那样做,这就是为什么我们需要了解您要解决的实际设计问题,以便我们可以从头开始提出建议。
  • @joshhunt - 如果您确实发布了另一个问题,您可以在评论中放一个链接,我会看看它。
  • @jfriend00 stackoverflow.com/questions/52248742/… 希望这是有道理的,谢谢!
【解决方案2】:

简短的回答是“否”——您不能将instanceof 与未定义的操作数一起使用。

但是,这并不一定意味着您无法发现一个对象是否是该类的一个实例。

instanceof 查看原型链。您可以手动执行相同的操作。这可能需要您使用一些鸭子打字来确定原型是否像Model 一样走路和嘎嘎声。

【讨论】:

    猜你喜欢
    • 2021-09-27
    • 2015-06-08
    • 2018-07-22
    • 1970-01-01
    • 2013-03-18
    • 2021-02-28
    • 2021-05-01
    • 1970-01-01
    相关资源
    最近更新 更多