Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
458 views
in Technique[技术] by (71.8m points)

javascript - How to access a constructor parameter inside a Typescript method

My Typescript Class contains the method getProductAttributeByName(name: string) which filters the collection defined as parameter of the constructor.

class Product {
    id: string;

    constructor(productDto: IProductDto) {
        this.id = productDto.id;
    }

    getProductAttributeByName(name: string): ProductAttribute {
        // I need productDto (the constructor parameter) here:
        return productDto.productAttributes.filter(x => x.name === name)
    }
}

This is not allowed, so currently I'm doing:

class Product {
    id: string;
    productDto: IProductDto;

    constructor(productDto: IProductDto) {
        this.id = productDto.id;
        this.productDto = productDto;
    }

    getProductAttributeByName(name: string): ProductAttribute {
        return this.productDto.productAttributes.filter(x => x.name === name)
    }
}

Needless to say that this is terrible. I'm exposing a public property which is only needed inside a method, for the only reason that I cannot access the constructor parameter. I also tried, out of desperation, to declare the property as private, like this:

class Product {
    id: string;
    private productDto: IProductDto;

    constructor(productDto: IProductDto) {
        this.id = productDto.id;
        this.productDto = productDto;
    }

    getProductAttributeByName(name: string): ProductAttribute {
        return this.productDto.productAttributes.filter(x => x.name === name)
    }
}

But this doesn't change the fact that the property is still accessible once the object has been initialized:

var product = new Product(myDto);
// product.productDto is accessible!

Is there a way to access a constructor parameter inside a method without having to declare a property that will be publicly accessible?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

"Just because my method cannot access a constructor parameter…" is thinking about this in the wrong terms. When instantiating your class, is productDto an important state of your instance? Does the data in productDto hold important information that Product needs during its lifetime? Then you're not merely trying to pass it between your constructor and some method, but that data is part of your object's state. And your object methods use and depend on that state. And object state is always implemented by object properties, so saving productDto on this.productDto is perfect fine and the right way to do it.

But this doesn't change the fact that the property is still accessible once the object has been initialized.

So what? Using TypeScript and the private declaration, TypeScript will ensure that you're not shooting your own foot by trying to access that property from outside code. That's all you need. There's no point in actually trying to enforce non-accessibility. You're just going to bend over backwards for hardly any gain. Many Javascript objects have internal state which you can poke around in if you so wish. That's no problem at all.

It's only a problem if you're actually writing code against these internal properties which aren't supposed to be part of the official API, and that internal implementation changes down the line. Simply don't do that. Again, TypeScript's private helps you enforce exactly that.

this.id = productDto.id;
this.productDto = productDto;

This is pretty redundant. Quite apparently you need productDto.id and productDto later on in other methods. Simply store the entire productDto as a property and access its .id as needed. If you need to expose the id as property on your class, using a get method which returns this.prodctDto.id is probably a sensible idea:

class Product {
    private productDto: IProductDto;

    constructor(productDto: IProductDto) {
        this.productDto = productDto;
    }

    get id(): string {
        return this.productDto.id;
    }

    getProductAttributeByName(name: string): ProductAttribute {
        return this.productDto.productAttributes.filter(x => x.name === name)
    }
}

In general, try designing your classes without writing the constructor first. Write everything but the constructor. Design which internal and external properties your class needs and which properties your methods will get their data from. Then, as the very last step, write your constructor which needs to ensure that the object state is such that all your methods can work as designed. Then the thinking of "passing from constructor to method" obviates itself.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...