javascript 用与父类相同的方法扩展类并返回对象,但构造函数不同

zvokhttg  于 2023-10-14  发布在  Java
关注(0)|答案(2)|浏览(97)

我试图从一个外部库中扩展一个类,该库包含在开始任何操作之前在输入中使用其构造函数的方法,因为它可以有多个类型。我想创建一个类,类似于它的工作,但输入是消毒。

class ParentClass {
    constructor(value: ParentClass.ValueType) {
        // ...
    }

    methodUsingConstructor(otherValue: ParentClass.ValueType) {
        const x = new this.constructor(otherValue)
        // do some stuff here with x ...
        return result;
    }

    // ...
}

如果我做

class SafeParentClass extends ParentClass {
    constructor(value: ParentClass.ValueType) {
        // Do some input sanitizing ...
        super(sanitizedValue);
    }
}

我可以使用new SafeParentClass(value)。但是,我将使用ParentClass的构造函数获取一个对象。这意味着如果我执行(new SafeParentClass(value1)).methodUsingConstructor(value2),那么value2没有被清理,我会得到一个错误。
我如何创建一个SafeParentClass,这样我就可以调用ParentClass的方法,并且它们将有一个清理输入的构造函数?
范例:

import { Decimal } from 'decimal.js';

class SafeDecimal extends Decimal {
    constructor(value: Decimal.Value) {
        if (typeof value === 'string') {
            super(parseFloat(value)); // will do super('NaN') if value is not parseable
        } else {
            super(value);
        }
    }
}

然后测试它

describe('safeDecimal', () => {
    it('should return NaN output with invalid input', () => {
        expect(new SafeDecimal('123123').add('').toString()).toEqual('NaN');
    });
});

它抛出一个DecimalError

icnyk63a

icnyk63a1#

问题在于decimal.js的写法。它将each instance上的constructor属性重写为Decimal(而不是允许它从原型继承,这是正常的事情)。它在当前decimal.mjsx.constructor = Decimal;)中的4,290行上执行此操作。它的注解说它这样做是为了隐藏继承的那个 ". which is Object ."(正常的做法是在insetad中修复继承的那个)。
你可以通过重写decimal.js的操作来解决这个问题:

class SafeDecimal extends Decimal {
    constructor(value: Decimal.Value) {
        if (typeof value === "string") {
            super(parseFloat(value)); // will do super('NaN') if value is not parseable
        } else {
            super(value);
        }
        this.constructor = SafeDecimal; // <=== Here
    }
}

然后,使用构造函数,计算示例工作(结果为NaN)。我没有测试过其他东西。

**在正常情况下,你不需要这个。**这是必要的,因为decimal.js的具体编写方式。

话虽如此,你可能想分叉它,并在分叉中做你认为需要做的修改。
最后,您可能需要考虑做一些比parseFloat更健壮的事情,因为parseFloat将很乐意为字符串"123asdlfkjasldf"返回123(而抛出错误或返回NaN可能更合理)。这里有一个答案,你可以选择各种工具来构建更健壮的东西。

t98cgbkg

t98cgbkg2#

恐怕,你必须在派生类中自己实现所有的方法。如果第三方类的方法的逻辑并不完全符合您的要求,您可以创建一个派生类并将原始方法引用为super.method(…)。使用这种技术,您可以首先清理输入,然后将其定向到原始方法。
基本上,你是这样做的:

class ThirdPartyClass {
  method(argument) {
    // the logic here unsafely uses the argument
  }
}
class DerivedClass extends ThirdPartyClass {
  override method(argument) {
    const safeArgument = sanitize(argument)

    return super.method(safeArgument)
  }
}

你必须对你使用的所有方法都这样做。

相关问题