我应该如何正确使用父类方法,并在typescript中使用关键字extends?

时间:2018-05-05 18:28:32

标签: angularjs typescript inheritance wrapper encapsulation

我有两个类,一个是父类,一个是子类,它们实现类型来定义它们的预期功能。那是在这里。

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();
}

我认为我严重过度思考继承和封装的想法,并会对如何进行并在务实的正确实践和有效/优化的代码之间取得平衡表示赞赏。

1 个答案:

答案 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) {}
}