【发布时间】:2023-03-30 22:47:01
【问题描述】:
我有一个抽象类:
public abstract class ParentClass<T, U> {
// a bunch of common code to prevent duplication in children
protected abstract adaptThese(...things: Array<MyType>): Array<T>
protected abstract adaptThose(...things: Array<MyType>): Array<U>
// some other non-generic abstract methods
}
这是一个示例子类:
public class ChildClass extends ParentClass<FirstType, SecondType> {
protected adaptThese(...things: Array<MyType>): Array<FirstType> {
//...
}
protected adaptThose(...things: Array<MyType>): Array<SecondType> {
//...
}
// implementations of the other abstract methods...
}
我的代码按原样工作,但问题是所有引用ParentClass 的代码都必须将其引用为ParentClass<any, any>。由于泛型类型纯粹用于内部目的(仅限protected 的东西),我想知道是否有一种好方法可以从父类中删除泛型类型,同时仍然为孩子们使用<T> 和@ 强制执行类型安全987654327@.
我最初引入这些泛型是为了强制子类提供从MyType 到T 和U 的某种适应,它们是依赖于库的,从不提供MyType。目标是允许我的项目的其余部分使用MyType,无论使用哪个底层库,因为它们在设计上都非常相似,但接受的类型不同。这将允许在不影响此层次结构之外的代码的情况下换入或换出所选包。 (我使用的是 Angular,所以这意味着只需将提供商的 useClass 更改为一行)。
我试图制作某种可以包含泛型的内部适配器对象,但我不知道如何强制子类声明和实现类似于上面的方法。
我得到的最接近的方法是在ParentClass 的MyAdapter<any, any> 类型的构造函数中添加一个参数,但我无法设法让any 成为一些在孩子们。
可能真正有用的一条信息是ParentClass 从不引用泛型方法本身,因此不一定需要声明它们以供ParentClass 使用。他们只是在那里强迫孩子们实施它们。也许我可以使用某种界面设计来实现这一点?
简而言之:如果有的话,我如何强制子级实现类型安全的方法而不在父级的签名中声明类型?
请求了一个示例,因此这里是一个简化的示例,如何拆分类型依赖:
在ParentClass,我可能有这样的方法:
// sets an array of things for a certain key (label)
setThingsFor(label: string) {
const thingsForLabel: Array<MyType> = myConfiguration.get(label);
// do some calculations, and filter things based on configuration
this.setThings(thingsForDisplay);
}
// sets an array of things for the feature
// this is public because the things can be set while avoiding the above calculations and configurations
abstract setThings(things: Array<MyType>): void;
在子类中:
public class CoolLibraryImplForParentClass extends ParentClass<CoolType, RadType> {
setThings(things: Array<MyType>): void {
// use "things" to determine some library-specific config
coolLibraryService.initialize(this.adaptThose(things)); // RadType
coolLibraryService.doThings(this.adaptThese(things)); // CoolType
}
// the generic methods and some CoolLibrary-specific things
}
有许多类似于上述的方法,用于工具或从库的服务中请求状态,需要这两种类型中的一种。
每个库的代码都非常相似,因此我为面向项目的代码引入了一个父类,并让子类使用依赖于库的细节。
此后我考虑的另一个问题是,我可能能够创建一个面向项目的服务类,然后为该类提供一个通用类型的库集成服务,但这是一个相当大的重写,我仍然对这个问题的答案。
【问题讨论】:
-
使用提供的代码,我将完全删除
T和U并让父类返回Array<any>。如果您有一些实际需要T和U类型(或类似类型)的约束,那么也许您可以添加更多代码来显示这些依赖关系? -
@jcalz 我添加了一个示例,感谢您的关注
-
嗯,我仍然不明白
ChildClass是如何关心这两种特定类型的。我认为您至少需要展示两个不同的子类实现,以便有人可以看到相同之处和不同之处。在这一点上,我仍然会说您不需要T和U并将其留给子类实现来使用他们想要的库。
标签: typescript generics