Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript 在运行时使用派生类扩展基实例_Typescript - Fatal编程技术网

Typescript 在运行时使用派生类扩展基实例

Typescript 在运行时使用派生类扩展基实例,typescript,Typescript,我有以下类层次结构: class Base { public BaseMethod() { // doesSomeStuff } } class Derived extends Base { constructor() { super(); } public DerivedMethod() { // do some stuff BaseMethod(); } } 我现在的问题是,在

我有以下类层次结构:

class Base {
    public BaseMethod() {
        // doesSomeStuff
    }
}

class Derived extends Base {
    constructor() {
        super();
    }
    public DerivedMethod() {
        // do some stuff
        BaseMethod();
    }
}
我现在的问题是,在运行时,我得到一个class
Base
的实例,我需要将该实例扩展为type
Derived
。我不控制
Base
的构造,也不是class
Base
的所有者

如何在运行时扩展该实例,使其成为派生类型的实例

function someFunction(base: Base) {
    let derived: Derived = extend(base);
    derived.BaseMethod();
    derived.DerivedMethod();
}
function extend(base: Base): Derived {
    // implementation?
}

PS:我需要瞄准ES5

这在ES6中可以使用。如果给
extend
函数一个
asserts
返回类型,您甚至可以使用控制流缩小,而不是使用更严格的类型返回输入:

函数扩展(base:base):断言base是派生的{
setPrototypeOf(base,派生的.prototype);
}
设b:Base=newbase();
延长(b);
b、 DerivedMethod();//好的,由于控制流变窄
警告:如果不小心,这允许您创建具有无效状态的对象。如果
Derived
类有自己的属性
foo
,那么调用
setPrototypeOf
会得到一个没有该属性的
Derived
对象。您有责任确保
extend
添加
派生的
对象所需的任何新属性


如果你的目标是早于ES6,有一个,但这只适用于谷歌浏览器和Mozilla Firefox;它通过更改
\uuu proto\uu
属性来工作,但此属性在ES6之前是非标准的,因此其他浏览器不支持它。为了扩展polyfill,似乎没有其他方法可以在其他浏览器中获取或设置对象的原型,因此如果您需要在其他浏览器上的ES5中执行此操作,那么您可能运气不佳


另一种解决方案可能是通过monkey patching,但是派生的
obj实例将为false,这意味着它实际上不是派生的
实例,这在ES6中是可能的。如果给
extend
函数一个
asserts
返回类型,您甚至可以使用控制流缩小,而不是使用更严格的类型返回输入:

函数扩展(base:base):断言base是派生的{
setPrototypeOf(base,派生的.prototype);
}
设b:Base=newbase();
延长(b);
b、 DerivedMethod();//好的,由于控制流变窄
警告:如果不小心,这允许您创建具有无效状态的对象。如果
Derived
类有自己的属性
foo
,那么调用
setPrototypeOf
会得到一个没有该属性的
Derived
对象。您有责任确保
extend
添加
派生的
对象所需的任何新属性


如果你的目标是早于ES6,有一个,但这只适用于谷歌浏览器和Mozilla Firefox;它通过更改
\uuu proto\uu
属性来工作,但此属性在ES6之前是非标准的,因此其他浏览器不支持它。为了扩展polyfill,似乎没有其他方法可以在其他浏览器中获取或设置对象的原型,因此如果您需要在其他浏览器上的ES5中执行此操作,那么您可能运气不佳


另一个解决方案可能是通过monkey patching,但派生的
obj实例将为false,这意味着它不会是派生的
实例,我根据@kaya3的答案找到了一个令人满意的解决方案。如果您不需要支持传统浏览器,请查看他/她的答案

对于
Object.setPrototypeOf
,有一个polyfill可供使用,它在传统IE浏览器(至少到IE9)中也可以使用。我在公园里找到的。它有一个警告,对象的引用需要重新分配

以下是我的解决方案:

class Base {
    public BaseMethod() {
        console.log('base called');
    }
}

class Derived extends Base {
    constructor() {
        super();
    }
    public DerivedMethod() {
        this.BaseMethod();
        console.log('derived called');
    }
}

function extend(base: Base): Derived {
    return <Derived>(Object.setPrototypeOf(base, Derived.prototype));
}
function assert(base: Base): asserts base is Derived { }

let b: Base = new Base();

b = extend(b);
assert(b);

b.BaseMethod(); // base called
b.DerivedMethod(); // base called derived called

根据@kaya3的答案,我找到了一个令人满意的解决方案。如果您不需要支持传统浏览器,请查看他/她的答案

对于
Object.setPrototypeOf
,有一个polyfill可供使用,它在传统IE浏览器(至少到IE9)中也可以使用。我在公园里找到的。它有一个警告,对象的引用需要重新分配

以下是我的解决方案:

class Base {
    public BaseMethod() {
        console.log('base called');
    }
}

class Derived extends Base {
    constructor() {
        super();
    }
    public DerivedMethod() {
        this.BaseMethod();
        console.log('derived called');
    }
}

function extend(base: Base): Derived {
    return <Derived>(Object.setPrototypeOf(base, Derived.prototype));
}
function assert(base: Base): asserts base is Derived { }

let b: Base = new Base();

b = extend(b);
assert(b);

b.BaseMethod(); // base called
b.DerivedMethod(); // base called derived called

是否必须将
基本
对象更改为
派生
对象?你能不能编写一个静态工厂方法来构造一个新的
派生的
对象,给定一个
对象来复制它的状态?@kaya3不,这对我来说是不可能的。否则,其他对象将丢失对该对象的引用。是否必须将
基本
对象更改为
派生
对象?你能不能编写一个静态工厂方法来构造一个新的
派生的
对象,给定一个
对象来复制它的状态?@kaya3不,这对我来说是不可能的。否则其他对象将丢失对该对象的引用。@daniatic我明白了。我在编辑中提到了polyfill,但这只适用于两种特定的浏览器,因为它依赖于这些浏览器的非标准功能。否则,似乎不太可能有解决方案,但可能不需要在运行时实际更改对象的类来解决实际问题。在这种情况下,您应该提出一个新问题,详细说明您希望在object.Thx上更改的具体行为,以便进行编辑。polyfill还是没用。我需要支持IE9+:(扩展实际类
Base
会解决您的问题吗?您可以在每个浏览器中分配新属性,如
Base.constructor.DerivedMethod=…
。这将扩展每个
Base
对象,包括已经存在的对象,而不必单独调用每个对象上的
extend
。)当然,如果您只想扩展某些实例,则不适用。这是个好主意,但仍然不是f