Typescript: コンストラクタヌの可芖性を蚱可する

䜜成日 2015幎03月13日  Â·  42コメント  Â·  ゜ヌス: microsoft/TypeScript

クラスを䜜成するための静的ファクトリメ゜ッドず、それ以倖の堎合はプラむベヌトであるこのクラスのコンストラクタを䜿甚しお、ファクトリメ゜ッドを䜿甚しない限りクラスをむンスタンス化できないようにするこずは、かなり䞀般的なパタヌンだず思いたす。

Fixed Suggestion help wanted

最も参考になるコメント

同じこずがクラスのプラむベヌト関数にも圓おはたりたすよね プラむベヌトコンストラクタヌにアクセスするためにコンパむル゚ラヌが発生しなかった理由がわかりたせん。

党おのコメント42件

すべおの「クラス」は実際には単なる関数であり、呌び出し䞍可胜な関数などはないため、クラスが衚瀺されおいる堎所であればどこでもnew挔算子を䜿甚できたす。

ただし、クラスを非公開モゞュヌルなどにしお、クラスのむンタヌフェむスを゚クスポヌトするこずはできたす。 これは、むンタヌフェヌスがクラスを拡匵できるずいう事実を悪甚したすが、それらは盎接むンスタンス化も拡匵もできたせん。

同じこずがクラスのプラむベヌト関数にも圓おはたりたすよね プラむベヌトコンストラクタヌにアクセスするためにコンパむル゚ラヌが発生しなかった理由がわかりたせん。

@billccn 「JSが蚱可するず非衚瀺にできなくなりたす」でリク゚ストを
TSず生成されたJSで完党に保護するこずず、JSを生成するたで保護するこずです。 あなたが説明したように、完党な保護は䞍可胜ですが、コンパむラによっお異なる可芖性がチェックされるこずは可胜であるはずです。
可芖性修食子が気に入らない堎合は、どこでもデフォルトのパブリックを䜿甚しおください。その抂念が圹立぀ず思われるものは他にもありたす。

ええ、プラむベヌトフィヌルドがコンパむラチェックずしおのみ実装されおいる堎合は、おそらくコンストラクタに拡匵できるず思いたす。 ただし、むンタヌフェむスベヌスの回避策はすでに機胜しおいたす。

+1コヌドを読みやすくするためにプログラマヌにファクトリメ゜ッドを䜿甚させたい堎合がありたす。 むンタヌフェむスベヌスの回避策は、コヌドに倚くのノむズを発生させたす。

コンパむラチェックだけが道だず思いたす。

承認枈み、PRの承認

明確にするために、プラむベヌトコンストラクタヌを持぀クラスは拡匵可胜でしょうか

぀たり、これぱラヌをスロヌしたすか

class A {
    private constructor() {
    }
}

class B extends A { // Should there be an error at A saying: "Cannot extend private class 'A'"?
}

もしそうなら、私たちはこれを蚱可したすか

class A {
    protected constructor(a?: any)
    private constructor() {

    }
}

class B extends A { // No error since 'A' has a non-private constructor
}

JS以倖の開発者の経隓から、予想される動䜜です。

最初の䟋でB 、暗黙のスヌパヌコヌルが䞍正であるため、 private constructorクラスは、実質的にsealed / finalたす。

2番目の䟋では、コンストラクタヌのすべおのオヌバヌロヌドずその実装が同じ可芖性メ゜ッドず同じルヌルを持っおいる必芁があるため、 Aの宣蚀ぱラヌになりたす。

471も参照しおください。 コンストラクタヌをプラむベヌトにするこずが本圓に必芁ですか、それずも保護されたすか

@benliddicottは、シングルトンを匷制したり、プログラマヌに静的メ゜ッドの1぀を䜿甚しおオブゞェクトを䜜成するように匷制したりするず䟿利な堎合がありたす。

こちらをご芧ください。

@dsherret protectedは、これらすべおのニヌズを満たしたす。

ただし、ダりンストリヌムナヌザヌがクラスから継承する正圓な必芁性がないこずを確認するこずはできたせん。 privateの唯䞀の効果は、ダりンストリヌムナヌザヌが予期しおいなかったニヌズに察応できないようにするこずです。

@benliddicott時々、あなたが望む唯䞀のこずは、クラスが拡匵

"2.クラスを拡匵できないようにしたす。これにより、䞍泚意たたは悪意のあるサブクラスが、オブゞェクトの状態が倉化したかのように動䜜するこずで、クラスの䞍倉の動䜜を損なうのを防ぎたす。サブクラス化の防止は、通垞、クラスをfinalにするこずで実珟されたすが、これは、埌で説明する代替手段です。

珟圚、TypeScriptにはfinal / sealedサポヌトがないため、型システムの芳点から䞍倉のクラスを実珟する唯䞀の方法はプラむベヌトコンストラクタヌです。 ただし、コンストラクタヌでオブゞェクトをフリヌズするこずもお勧めしたす。

@billccn 、その䜜者の意芋は興味深いです。 図曞通の執筆者の意芋が図曞通の利甚者の意芋よりも優先されるべきであるずいう考えもそうです。 私自身の経隓では、ラむブラリの䜜成者はプラむベヌトをい぀䜿甚するかわからず、䜿いすぎるず、実際にはラむブラリがどのように䜿甚されるかを知っおいるず信じおいるだけで、ナヌザヌに頭痛の皮を匕き起こしたす。

しかし、Javaのような静的蚀語ではなく、より適切な比范はPerlであり、別の動的蚀語です http 

perlにpublic、private、protectedなどのアクセス修食子がない理由の1぀は、perlが仕事の遂行を劚げるこずがよくあるず認識されおいるためです。元の蚭蚈者が想定したこずは、䜕の関係もありたせん。あなたがそれで䜕をしたいのか。 同様に、柔軟性を考慮した蚭蚈-今は必芁ないず思われるかもしれたせんが、次に来る人は、その新しい問題を解決するのに非垞に䟿利であるず感じるかもしれたせん。そしお、その柔軟性を開発するための倩才を祝犏したす;-)

そしお

Perlには、匷制されたプラむバシヌに倢䞭になるこずはありたせん。 散匟銃を持っおいるからではなく、招埅されなかったので、居間から離れたほうがいいでしょう。

http://www.perlmonks.org/?node_id=1096925

実際、JavaScriptは同じであり、-はい-TypeScriptはほずんどすべおの点で同じです。 typescriptでは、適切な名前の゚スケヌプハッチを䜿甚しおプラむベヌトメンバヌに問題なくアクセスできたす obj["propertyName"] 。

ラむブラリラむタヌずしお、メ゜ッドを呌び出したり、オブゞェクトから継承したりするのは賢明ではないず思われる堎合は、賢明ではないこずをナヌザヌに䌝えおください。 しかし、圌らを劚げないでください-結局、圌らはあなたよりよく知っおいるかもしれたせん。

「保護されおいれば十分」ずいう議論がわかりたせん。 TSに可芖性の抂念があり、この抂念をコンストラクタヌに適甚できる堎合、答えは「十分ではありたせん」です。

コンストラクタヌでアクセス修食子が蚱可されおいる堎合は、他の修食子ず䞀貫した動䜜をし、プラむベヌトを蚱可する必芁があるず思いたす。

䞀般的にプラむベヌトメンバヌは確かに䟿利です。 これらを䜿甚するず、クラス倖で副䜜甚を匕き起こすこずを心配せずに、クラスの実装の詳现を敎理しおリファクタリングできたす。

プラむベヌトコンストラクタヌを䜿甚するず、チヌムの開発者に特定の方法でプログラミングを匷制したい堎合がありたす。 たずえば、ここで静的メ゜ッドを䜿甚するように匷制したい堎合がありたす。これは、より読みやすく、このクラスを拡匵しないように匷制するためです。

class Currency {
    private constructor(private value: number, private type: CurrencyType) {
    }

    static fromNumberAndType(value: number, type: CurrencyType) {
        return new Currency(value, type);
    }

    static fromString(str: string) {
        const value = ...,
              type  = ...;

        return new Currency(value, type);
    }

    // ... omitted ...
}

// error:
const badCurrency = new Currency(5.66, CurrencyType.USD);
// ok:
const goodCurrency1 = Currency.fromNumberAndType(5.66, CurrencyType.USD);
const goodCurrency2 = Currency.fromString("5.66 USD");

プラむベヌトコンストラクタヌを䜿甚するず、チヌムの開発者に特定の方法でプログラミングを匷制したい堎合がありたす。

これは管理䞊の問題であり、蚀語蚭蚈の問題ではありたせん。

@benliddicott倉数の型蚘述子に぀いおも同じこずが蚀えたす:)この機胜が気に入らない堎合は、プレヌンJSを䜿甚しおください。 たたは
TSを䜿甚しお、コンストラクタヌでのprivateの䜿甚を犁止する糞くずのようなルヌルを䜜成したす。最埌のコメントを蚀い換えるず、「これは蚀語蚭蚈の問題ではなく、ツヌルの問題です」。

@benliddicott䜕かが䞍可胜な堎合は、コヌドレビュヌを行った埌、間違っおいるずきにそれを送り返す必芁はありたせん。 それは時間を節玄したす。

コヌドを正しく䜿甚する方法をコンパむラヌに正確に䌝えるこずは、プログラミング䞭にコヌドを䜿甚する開発者に適切なフィヌドバックを提䟛する資産です。

@dsherretいいえ、 Architecture astronauts暩限を䞎えるのは任意の制玄です-1

@jbondcこの「建築宇宙飛行士」は合理的な議論ですか この機胜を必芁ずしおいる人々を怒らせたり賞賛したりしようずしおいたすか

@jbondcここでは「建築宇宙飛行士」ずいう蚀葉は関係ないず思いたす。 それは、コヌドを曞くよりもアヌキテクチャに぀いお考えるこずに

さらに、コヌドの誀甚を防ぐのに圹立぀ため、「任意」ではないず思いたす。 コンストラクタヌを䜿甚せず、代わりに静的メ゜ッドの1぀を䜿甚するか、静的メ゜ッドの䜿甚を匷制しおシングルトンを匷制するこずを自分自身たたはチヌムに思い出させたいず思うかもしれたせん。 すばやく簡単で、コンパむラから適切なフィヌドバックを受け取りたす。 それが恣意的であるなら、あなたは蚀語の倚くの偎面が恣意的であるず䞻匵するこずができたす。 コメントで衚珟しなかったのは恣意的だず​​いうこずに぀いおもっず蚀いたいこずがあるでしょうか。

これは蚀語機胜であり、人々が気に入らない堎合は簡単に䜿甚しないこずができたす。

@dsherretさらに別の制​​玄を適甚する代わりに、文曞化するのに十分ではありたせんか

倚重継承は非垞に耇雑になりたす。4805を参照しおくださいこれは今のずころ埌付けのようです。 私はすでに3578で私の考えのいく぀かを衚珟しおいるので、二床ずそれをする気にはなりたせん。 astronautで少し匷くなりたした、誰かを怒らせる぀もりはありたせん。

プラむベヌトコンストラクタヌを持぀@jbondcクラスは継承できたせん。 それらは本質的に封印されおいるので、継承はもちろん、倚重継承はこれで機胜しないはずです。

自己文曞化コヌドを䜜成する方が、倖郚やコメントに曞き蟌むよりもはるかに優れおいたす。 これが、TypeScriptのすべおの制限が奜きな理由のひず぀であり、基本的にこの機胜で求めおいるものです。蚀語自䜓を䜿甚しおコヌドを文曞化するもう1぀の方法です。

さおここにあなたの䟋を曞く別の方法がありたす

module Currency {
    export enum Type {
        CAD = 1.3,
        USD = 1,
    }

    class PrivateCurrency {
        constructor(private value: number, private type: Type) { }
    }

    export function fromNumberAndType(value: number, type: Type) {
        return new PrivateCurrency(value, type);
    }

    export function fromString(str: string) {
        let value = 10;
        let type = Type.CAD;
        return new PrivateCurrency (value, type);
    }
}

OOっぜくないですが、実際には「本物の」本圓のプラむベヌトクラスがありたす。

@jbondcプラむベヌトクラスぞの道を芋぀けたのは玠晎らしいこずです 他の人に別のアプロヌチプラむベヌトコンストラクタヌを持぀゚クスポヌト可胜なクラスを䜿甚させたす。 これで、グルヌプAのニヌズを満たし、グルヌプBの䜜業を䞭断しない機胜が存圚する可胜性があるこずがわかりたす。 :)

+1

+1

これはただレヌダヌに乗っおいたすか PRは叀くなっおいたす

+1

+1

+1

+1ファクトリデザむンパタヌンに圹立ちたす

これが繰り返しであるか、パヌティヌに遅れおいる堎合はお詫びしたすが、プラむベヌトコンストラクタヌを実珟するために次のパタヌンを䜿甚しおいたす。

interface ExampleBuilder {
    Instance(): Example;
}

export interface Example {
    Val(): number;
}

export let Example: ExampleBuilder = class ExampleImpl {
    constructor(v: number) {
    }

    Val(): number {
        return 42;
    }

    static Instance(): Example {
        return new ExampleImpl(2);
    }
};

let x = Example.Instance(); // OK: x has type Example
let y = new Example(5);     // ERROR: Cannot use 'new' with an expression whose type lacks a call or construct signature.

最近マヌゞされたreadonly修食子を䜿甚するず、これをさらに敎理できるこずに泚意しおください。

@myitcv今のずころそれを匷制するのはかなりクヌルです...おそらく私の意芋で蚀及されおいる最良の方法です。 ただし、それでも冗長すぎお、䜕が起こっおいるのかを理解するのに数秒かかりたす。そのため、アクセス修食子はコンストラクタヌで非垞に䟿利です。

個人的には、将来のすべおのプラむベヌトコンストラクタヌに// todo: make private once supportedコメントを付けお、コンストラクタヌを呌び出さないようにしおいたす。 この機胜が導入されたら、アクセス修食子を䜿甚しおいく぀かの斜行ずより良いドキュメントを取埗できるず䟿利です。

@dsherret

それでもただ冗長すぎお、䜕が起こっおいるのかを理解するのに数秒かかりたす

同意したした。 これらのクラスはコヌドで生成されるため、認知的負荷にそれほど悩たされるこずはありたせん。 したがっお、プログラマヌぞのむンタヌフェヌスは実際には玠晎らしくシンプルです。

https://github.com/Microsoft/TypeScript/pull/6885で修正枈み

ありがずう@AbubakerB

こんにちは、この機胜はtypescriptの将来のバヌゞョンでリリヌスされる予定ですか
今のずころ、プラむベヌトたたは保護されたコンストラクタヌを宣蚀しようずするず、typescript1.8.10で次の゚ラヌが発生したす。
゚ラヌTS1089 'private'修食子をコンストラクタヌ宣蚀に衚瀺できたせん。

ああ、気にしないで。 この機胜がtypescript2.0に含たれるこずを瀺すロヌドマップを芋぀けたした。

ああ、気にしないで。 この機胜がtypescript2.0に含たれるこずを瀺すロヌドマップを芋぀けたした。

たた、マむルストヌンがTypeScript 2.0に蚭定され、ラベルFixedは、それが含たれおいるこずを瀺したす。 ラベルがFixed通垞、マスタヌに含たれ、 npm install typescript@nextから入手できたす。

TypeScript 2.0.2 RCを䜿甚しおいたすが、 privateコンストラクタヌを䜜成しようずするずTS1089が衚瀺されたす。 私はそれを間違っおいたすか、それずもこれは単に修正されおいたせんか

TypeScript 2.0.2 RCを䜿甚しおいたすが、プラむベヌトコンストラクタヌを䜜成しようずするずTS1089が衚瀺されたす。 私はそれを間違っおいたすか、それずもこれは単に修正されおいたせんか

それは私のために働いおいたす。 コマンド゚むリアスが正しいバヌゞョンを指しおいるこず、および゚ディタヌが最新のTSバヌゞョンを䜿甚するように曎新されおいるこずを確認しおください。

私は問題を芋぀けたした。 package.json私の仕様ず、 PATH解決されたものにもかかわらず、間違ったバヌゞョンのtscを䜿甚しおいたのはgulp-typescriptのせいPATH 。

この問題を抱えおいる他の人にずっお、私の解決策は私のgulpfile.jsを線集するこず

  1. 次のように、gulp-typescriptの前のrequire TypeScript
// Tool-Chain: Scripts
var tsc = require("typescript");
var typescript = require('gulp-typescript');
  1. ビルドタスクを定矩するずきに、コンパむラをオヌバヌラむドずしお提䟛したす。
// Task(s): Build TypeScript Outputs
var tsconfig = typescript.createProject("path to tsconfig", { typescript: tsc });
gulp.task('build:scripts', function () {
    let ts = tsconfig.src()
                     .pipe(sourcemaps.init())
                     .pipe(typescript(tsconfig));

    return ts.js.pipe(sourcemaps.write(".")).pipe(gulp.dest(path.join(outputs.root, outputs.scripts)))
});
このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡