Object 如何改进Typescript中的对象设计?
我已经在Typescript中创建了一个实现简单流(FRP)的类。现在我想用客户端功能(事件流)扩展它。为了说明我的问题,下面是一些伪代码:Object 如何改进Typescript中的对象设计?,object,design-patterns,typescript,functional-programming,Object,Design Patterns,Typescript,Functional Programming,我已经在Typescript中创建了一个实现简单流(FRP)的类。现在我想用客户端功能(事件流)扩展它。为了说明我的问题,下面是一些伪代码: class Stream<T> { map<U>(f: (value: T) => U): Stream<U> { // Creates a new Stream instance that maps the values. } // Quite a few other
class Stream<T> {
map<U>(f: (value: T) => U): Stream<U> {
// Creates a new Stream instance that maps the values.
}
// Quite a few other functions that return new instances.
}
ClientStream
类重写此函数以返回ClientStream
实例。但是,编译器抱怨ClientStream.map
返回的是Stream
,而不是ClientStream
。这可以通过使用石膏来“解决”,但除了丑陋之外,它还可以防止链接
显示此问题的示例代码:
class Stream {
protected create(): Stream {
return new Stream()
}
map() {
return this.create()
}
}
class ClientStream extends Stream {
protected create(): ClientStream {
return new ClientStream()
}
watch() {
return this.create()
}
}
let s = new ClientStream().map().watch()
这不会编译,因为根据编译器,从map
返回的流不是ClientStream
:错误TS2339:类型“stream”上不存在属性“watch”。
我真的不喜欢这种模式,但我没有其他更优雅的解决方案。我想到的事情:
- 使用构图(装饰器)。考虑到我需要代理的方法的数量,这不是一个真正的选择。我希望以后能够将方法添加到
,而不必担心Stream
ClientStream
- 将
混合到Stream
中。或多或少,同样的问题,ClientStream
必须知道将要混合的函数的签名(或者不知道?请告诉我)ClientStream
- 将这些类合并为一个类。这是万不得已的办法,
功能与服务器无关watch
你有更好(更优雅)的解决方案吗?如果你有一个更接近实用风格的想法,我很乐意听到。谢谢 你想做的事叫做 在TypeScript中,这是通过
this
关键字完成的。请看一看Typescript的文档以了解。如果遵循文档,您应该能够实现您想要的:-)
实际上,只要确保在成员方法中返回
这个
,就可以了 你想做的事叫做
在TypeScript中,这是通过this
关键字完成的。请看一看Typescript的文档以了解。如果遵循文档,您应该能够实现您想要的:-)
实际上,只要确保在成员方法中返回
这个
,就可以了 工厂方法可以是静态的吗?或者它们依赖实例数据吗?是的,它们可能是静态的。你可以像@SebastianSebald所说的那样使用多态this types
,但是你的类是泛型的,这会使它变得更难。但我仍在努力理解你的问题。你能用一个完整的例子来更新你的代码吗?我可以粘贴到游乐场上,看看错误是什么,在哪里。我明天会这样做,提前感谢您的关注。我不理解您的示例。newclientstream()
创建一个实例,然后调用其map()
方法,该方法创建同一ClientStream
类的新实例,并在该类上调用watch()
方法,该方法创建Stream
的新实例,但ClientStream
扩展了Stream
。这一切有什么意义?您有一个ClientStream
/Stream
实例,第一个new ClientStream()
。工厂方法可以是静态的吗?或者它们依赖实例数据吗?是的,它们可能是静态的。你可以像@SebastianSebald所说的那样使用多态this types
,但是你的类是泛型的,这会使它变得更难。但我仍在努力理解你的问题。你能用一个完整的例子来更新你的代码吗?我可以粘贴到游乐场上,看看错误是什么,在哪里。我明天会这样做,提前感谢您的关注。我不理解您的示例。newclientstream()
创建一个实例,然后调用其map()
方法,该方法创建同一ClientStream
类的新实例,并在该类上调用watch()
方法,该方法创建Stream
的新实例,但ClientStream
扩展了Stream
。这一切有什么意义?您有一个ClientStream
/Stream
实例,第一个new ClientStream()
。谢谢您的建议。我可能错了,但这不仅仅是建筑模式吗?这里涉及到可变状态,我想阻止它。额外的.currentValue()
调用也是如此(对于构建器来说很典型)。我不确定这是否是构建器模式。我在wikipedia上查到了它,我也一样,它看起来似乎与wie类继承有关。如果我错了,请纠正我。在哪里可以看到可变状态?在typescript站点上的计算器示例中,此值对于每次计算都会进行修改。关于构建器模式,它是一种通过几个步骤构建某些产品的模式。在我看来,这就是计算器的作用。即使它“只是”一个数字,结果仍然是通过多个步骤得到的,并且必须通过额外的方法调用(currentValue
)从“生成器”中检索。啊,现在我明白你的意思了。我建议返回一个新实例。因此,不要返回此
,而是返回新流
。你想做的与RxJS非常相似,也许阅读也会有所帮助。谢谢你的建议。我可能错了,但这不仅仅是建筑模式吗?这里涉及到可变状态,我想阻止它。额外的.currentValue()
调用也是如此(对于构建器来说很典型)。我不确定这是否是构建器模式。我在wikipedia上查到了它,我也一样,它看起来似乎与wie类继承有关。C
protected create<U>(.....): Stream<U> {
return new Stream<U>(.....)
}
class Stream {
protected create(): Stream {
return new Stream()
}
map() {
return this.create()
}
}
class ClientStream extends Stream {
protected create(): ClientStream {
return new ClientStream()
}
watch() {
return this.create()
}
}
let s = new ClientStream().map().watch()