/**
* p_value 这个属性用户不感知
*/
abstract class A<T, P> {
protected p_value: P;
protected t_value: T;
}
/**
* B 和 C 是 A 的子类,虽然 p_value 类型不一样但是存在这一属性
*/
class B<T> extends A<T, number> {}
class C<T> extends A<T, string> {}
/**
* 用户在 doSomething 的时候需要类型抽象,但是 p_value 不确定,是不感知的
*/
function doSomeThing(objA: A<number, unknown>, objB: A<number, unknown>) {}
/**
* 例如 b 和 c 都是 number 类型
*/
const b = new B<number>();
const c = new C<number>();
doSomeThing(b, c);
/**
* 问:有没有办法优化这个架构,让 A 自动推断 P 类型
*/
1
shigella 2022-08-10 17:22:56 +08:00
emmm
范型 P 定义在 A (因为 A 内需要 P 的类型才能完成具体实现),这个 P 一定需要由外部传递。那就两条路可以传入 1. 从派生类的类型定义声明具体 P 类型,子类不再对 P 类型参数继续扩展。扩展通过更多的子类实现,你需要在 A 内完成针对 P 的所有通用的抽象实现; 2. 继续将 P 作为范型参数(为了继续扩展或派生类 BC 需要 P 的类型去完成具体实现),由 new 的时候传入。子类的目的是为了针对特定类型的 P 完成具体实现。 |
2
shigella 2022-08-10 17:29:56 +08:00
有点问题修正一下……
范型 P 定义在 A (因为 A 内需要 P 的类型才能完成具体实现),这个 P 一定需要由外部传递。那就两条路可以传入 1. 从派生类 BC 的类型定义声明具体 P 类型,孙类不再对 P 类型参数继续扩展。扩展通过更多 A 的子类达成,你需要在 A 内完成针对 P 的所有通用的抽象实现; 2. 继续将 P 作为范型参数(为了能够在孙类继续扩展针对 P 的逻辑 或 子类 BC 需要 P 的类型去完成具体实现),由 new 的时候传入。子类 BC 的目的是为了针对特定类型的 P 完成具体实现。如果不是出于这个目的就没必要选这条路。 |
3
shigella 2022-08-10 17:35:31 +08:00
如果你不需要 P 的类型去实现逻辑,确实直接就 object 就完事了。
但是在 A 里面定义范型参数 P ,那说明一定是依赖的 P 的类型去干活了 这个依赖可以是因为内部反射,或者针对不同类型要 switch case ,或者是需要提供范型的返回值类型诸如此类。 |