我有两个类,一个是父类,一个是子类,它们实现类型来定义它们的预期功能。那是在这里。
export abstract class BaseLogService implements IBaseLogService
{
static $inject: string[] = ['$http']
constructor(private $http:ng.IHttpService){
}
baseMethod1 = (objToLog): void => {
//do stuff
}
baseMethod2 = (objToLog): void => {
//do stuff
}
}
class LocalLogService extends BaseLogService implements ILocalLogService
{
constructor(private $http:ng.IHttpService){
super(this.$http);
}
localMethod1 = (): void => {
//do stuff
}
}
export interface IBaseLogService {
baseMethod1(objToLog):void;
baseMethod2(objToLog):void;
}
export interface ILocalLogService extends IBaseLogService{
localMethod1(): void;
}
该应用程序使用日志服务,并为不同的公司记录内容。对于公司A,与公司B和C相比,它可能会记录一些不同的东西。这就是每个公司都有本地日志服务的原因。但是所有公司都记录了普遍的事情。所以这就是本地实现扩展的常见Log类的原因。
在我的问题出现之前,我如何恰当地利用我的父母班级'方法
为了扩展它,让我解释一下这是如何使用的。这是angularjs所以在应用程序的其他地方的控制器中有一个api POST调用。
在该调用的承诺中,在.then()中返回,需要执行baseMethod1来记录一些常见的东西。所以它就像下面的伪代码
myThingToAdd: any;
static $inject: string[] = ['localLogService']
constructor(private localLogService: ILocalLogService){}
this.myPOSTApi.addAThing(this.myThingToAdd)
.then((POSTResponse) => {
this.localLogService.baseMethod1(POSTResponse);
});
这是我的困惑发挥作用的地方。我有一些公司特定的东西需要在调用baseMethod1时发生。但是因为我的服务调用从控制器直接进入父类,所以我跳过本地逻辑需要发生的本地子服务。
我可以设置它,所以我的.then()服务调用转到我的本地子类,它在调用super.baseMethod1()之前执行我公司特定的逻辑,但这看起来非常间接,因为我能够打电话给父母班级'直接来自我在控制器中注入的服务。
然后我想,我可以打两个电话,一个用于本地逻辑,一个用于通用,每个用于各自的服务,但这似乎并不适合我。感觉它违背了继承的目的。
然后我走下兔子洞,想到了我现在的位置。
我的父类方法是否应该对应用程序的其余部分不可见,并且只能在我的子类中使用?如果是这样,混淆有多深?如果我的子类有公开公开的方法,那就直接调用super.baseMethod1()
localMethod1 = () => {
//local logic
super.BaseMethod1();
}
或者甚至太直接了?我应该有一个公开暴露的子方法,然后调用一个调用我的超级方法的私有内部方法?像
localMethod1 = () => {
//local logic
this.callSuperMethod1();
}
private callSuperMethod1 = () => {
super.baseMethod1();
}
我认为我严重过度思考继承和封装的想法,并会对如何进行并在务实的正确实践和有效/优化的代码之间取得平衡表示赞赏。
答案 0 :(得分:1)
继承正是解决这个问题的方式:
我可以设置它,所以我的.then()服务调用转到我的本地子类,它在调用super.baseMethod1()之前执行我公司特定的逻辑,但这看起来非常间接,因为我能够打电话给父母班级'直接来自我在控制器中注入的服务。
子类可以实现自己的baseMethod1
,也可以通过super
方法调用来应用父级的行为。正如this answer中所解释的,继承是不应该使用实例箭头方法的几个原因之一。这不会起作用,因为实例方法无法访问super
:
localMethod1 = () => {
//local logic
super.BaseMethod1();
}
是:
export abstract class BaseLogService {
...
constructor(protected $http:ng.IHttpService) {}
baseMethod1(objToLog): void {
//do stuff
}
...
}
class LocalLogService extends BaseLogService {
// can be omitted
constructor($http:ng.IHttpService){
super($http);
}
baseMethod1(objToLog): void {
super.baseMethod1(objToLog)
//do stuff
}
}
如果ILocalLogService
完全复制了公共BaseLogService
界面,那么它是多余的 - BaseLogService
可以用作界面。 $http
应为protected
而不是private
,因为它可能会用于子类。 Visiblility修饰符应仅在父构造函数中指定一次。如果子构造函数除了调用super
之外什么都不做,则可以省略它。
由于一次只能使用一个记录器类,因此这就是DI模式的用途。这可以通过AngularJS DI来解决:
// company A module
app.service('logger', ALogService);
使用该服务的单位不应该知道他们正在使用哪种实现:
FooController {
constructor(public logger: BaseLogService) {}
}