Typescript: معدّل وصول مختلف لـ getter و setter

تم إنشاؤها على ٢١ أبريل ٢٠١٥  ·  40تعليقات  ·  مصدر: microsoft/TypeScript

هل يمكن تنفيذ مُعدِّل وصول مختلف لـ getter و setter؟ وبهذه الطريقة ، يمكن أن يكون الواضع على سبيل المثال خاص / محميًا وجامعًا عامًا. في بعض الحالات يكون هذا مفيدًا حقًا عندما تكون القيمة للقراءة فقط.

مثال:

class MyClass {
    private _myProp: any;
    private set myProp(value: any) {
        this._myProp = value;
    }
    public get myProp(): any {
        return this._myProp;
    }
}
Declined Suggestion Too Complex

التعليق الأكثر فائدة

على أي حال إضافة +1 الخاصة بي لهذا ، في حالة إعادة النظر فيه في المستقبل ...

ال 40 كومينتر

12

نظرًا لأن رقم 12 مغلق بالرقم 6532 # الآن ، يبدو أن هذه المشكلة خارج النطاق.
هل لديك الآن أي خطط لتنفيذ مُعدِّلات وصول مختلفة؟
لأن readonly غير كافٍ لحل ما هو موصوف هنا حيث أن الخاصية قد تكون قابلة للكتابة بالفعل داخل الفصل.

أعتقد أنه يجب علي أيضًا نقل المثال الخاص بي هنا من قضية ذات صلة:

declare abstract class Emitter {
    new (): Emitter;
    on: (name:string, handler: (arg:any) => void) => void;
    off: (name:string, handler: (arg:any) => void) => void;
    protected emit: (name:string, arg:any) => void;
}

class Person extends Emitter {
    constructor(name:string) {
        super();
        this.name = name;
    }

    private _name:string;
    get name() {
        return this._name;
    }
    set name(value) {
        if (this._name !== value) {
            this._name = value;
            this.emit('change:name', value);
            //this way is better
            this.updatedAt = new Date();
            //than this way
            this.setUpdatedAt(new Date());
        }
    }

    ////
    private _updatedAt:Date;
    get updatedAt() {
        return this._updatedAt;
    }
    private set updatedAt(value) { //Getter and setter do not agree in visibility
                //some logic and a simple readonly (our absence of a setter) is not enough
        if (this._updatedAt !== value) {
            this._updatedAt = value;
            this.emit('change:updatedAt', value);
        }
    }

    //// method implementation - but what's the point in it?
    private setUpdatedAt(value) {
        if (this._updatedAt !== value) {
            this._updatedAt = value;
            this.emit('change:updatedAt', value);
        }
    }
}

const entity = new Person('Mike');
entity.on('change:updatedAt', console.log.bind(console));
entity.name = 'Thomas';
//but manually setting updatedAt should be forbidden
entity.updatedAt = new Date(); //restricted

هنا ، يمكن أن تحتوي الخاصية updatedAt فعليًا على أداة ضبط ولكن لا ينبغي الوصول إليها خارج Person . علاوة على ذلك ، يحتوي هذا الواضع على منطق معقد وقراءة بسيطة فقط أو عدم وجود واضع لا يكفي.

أوافق على أن الواضع الخاص هو مجرد بناء جملة للطرق الخاصة ذات المنطق الإضافي (مثل البث) لكنني أعتقد أنه غير متسق عندما يكون جزء من المنطق المرتبط بحقل ما في خاصية (getter) وآخر في طريقة (واضع خاص) .

وبهذه الطريقة يتم تنفيذ الحاصل / المحددات في C# ، أعتقد أنه سيكون من المفيد السماح برؤية مختلفة في وقت التجميع ، على الرغم من أن هذه العقود ستضيع في وقت التشغيل.

التوصية هنا هي استخدام أداة تجميع عامة للقراءة فقط وحقل دعم خاص / محمي.

الموصلات متناظرة مع الخصائص في نظام الكتابة. أي شيء نفعله يجب أن يتجلى في النوع ويمكن التعبير عنه في الخصائص. ستؤدي إضافة معدّلات وصول جديدة لتمكين private_set / public_get من تعقيد اللغة ومنحنى التعلم ، ولن تتطابق القيمة المكتسبة من هذا مع التعقيد الإضافي.

على أي حال إضافة +1 الخاصة بي لهذا ، في حالة إعادة النظر فيه في المستقبل ...

ما زلت أرغب في رؤية هذا. يمتلكها C # ، وهي مفيدة بشكل لا يصدق في العديد من الظروف ، خاصة عندما يكون لديك أعلام تريد أن تقرأ خارجيًا للفصل ، ولكن يتم تعيينها داخليًا فقط مع خاص / محمي.

أعتقد أن الاقتراح بعدم استخدامه كثيرًا ما هو مهزلة من حيث أن النمط غير مستخدم لأنه غير متاح للاستخدام.

هذه إضافة جيدة للغة: مقدار التعقيد الذي سيضيفه هذا (من منظور المبرمج المطبوع عليه) صغير. المفهوم سهل الفهم ويجب أن يكون المترجم قادرًا على تقديم رسائل خطأ جيدة تلمح إلى سبب عدم قدرتك على الوصول إلى الحاصل أو المحددات بسبب تحديد النطاق.

أتفق مع المستخدمين المذكورين أعلاه ، هذا معيار لمعظم اللغات الأخرى. الحجة ضدها لا وزن لها ويجب إعادة النظر في التنفيذ.

لقد فوجئت بالفعل بعدم قدرتك على القيام بذلك في TS ... +1 لهذه المشكلة.
لا ينبغي أن يكون هناك أي منحنى تعلم متزايد مع هذا

private get x() { ... }
public set x(value) { ... }

إذا كنت تستطيع قراءة اللغة الإنجليزية ، فمن الواضح أن المقصود هنا هو خاص (محمي) / عام. وأيضًا إذا كنت تقوم بتعريف الموصِّلات في المقام الأول - فربما تعرف بالفعل الغرض منها.

ملاحظة حول الخطأ: "لا يتفق مستخدمو Getter و setter في الرؤية" - حسنًا: هذا بالضبط ما أريدهم أن يفعلوه

فيما يلي حالتا استخدام حيث يكون ذلك مفيدًا:

Backbone.js ، لتجنب المكالمات القبيحة .get() و .set() :

class Whatever {
    public get rotation(): number {
        return this.get('rotation');
    }
    private set rotation(rotation: number) {
        this.set('rotation', rotation);
    }
}

الخصائص التي يمكن للفئات الفرعية تعديلها:

class ExtendMe {
    public get someProperty(): string {
        // some stuff
    }
    protected set someProperty(prop: string) {
        // some stuff
    }
}

أود بالتأكيد أن أرى هذا ، لأنه كان يزعجني منذ أن بدأت في استخدام TypeScript.

أنا أتفق مع الأشخاص الذين يطلبون هذه الميزة. لقد حاولت للتو الحصول على طريقة () عامة وفوجئت برؤية أن مجموعتي والحصول عليها يجب أن يتفقان على الرؤية.

لقد كنت أقرأ يا رفاق وهم يزعمون أنه معقد للغاية. تذكر "طريقة C ++" سبب اختلافها عن:

private _myAttribute: string;
get myAttribute(): string {...}
setMyAttribute(value: string) {...}

أستطيع أن أرى الكثير من حالات الاستخدام لهذا ، ولهذا السبب أنا هنا الآن.
ماذا لو أردت أن تكون سمة myAttribute متاحة للجمهور مع السماح فقط بتعديلها داخل فئتها؟
ماذا لو أردت إضافة منطق مخصص في كل مرة يتم فيها تعديل السمة؟
يمكن أن تكون قاعدة عمل ، يمكن أن تكون مجرد تسجيل لفهم سبب تخصيص قيمة معينة لها ، جنبًا إلى جنب مع شرط نقطة التوقف لأغراض التصحيح ، إلخ ...

في الأساس ، نريد طريقة لاستخدامها في كل مرة نقوم فيها بتعديل السمة مع السكر النحوي الذي يجعل الأمر يبدو أننا نعيّن قيمة فقط ، بدلاً من استدعاء طريقة.
لدى C # مفهوم الخصائص لهذا وأعتقد أن TS ورث هذا المفهوم ، لكن عدم السماح بإمكانيات وصول مختلفة يمثل قيودًا كبيرة للأشخاص الذين يفكرون مثلي ويجعلنا نعود إلى "نمط C ++".

لا ينبغي أبدًا أن تكون عبارة "إنه صعب للغاية" سببًا لعدم تنفيذ ميزة مفيدة بشكل لا يصدق.

إضافة بلدي +1. يبدو غريباً للغاية بالنسبة لي أنه لا يمكنك فعل ذلك بلغة تكون تمامًا من نواحٍ عديدة.

فوجئت عندما وجدت أن هذه المشكلة تم وضع علامة عليها على أنها مغلقة. هذه الميزة مطلوبة من قبل المجتمع. يرجى إعادة الفتح.
+1

12 لا يعالج هذه المشكلة ، لذا لا ينبغي إغلاق هذه المشكلة بتعليق يشير إلى هذه المشكلة.

IMHO هذه ميزة رائعة ولكن بقدر ما أفهم من العدل أنها مجرد حالة "حسنًا ، لا أريد أن أكتب في كل مرة _property بدلاً من ذلك أريد استخدام خاصية المجموعة الخاصة"

إذا كان هناك خيار إما إضافة تعقيد كبير إلى كود TypeScript الأساسي نفسه (تذكر ، المزيد من التعقيد غير الضروري - سرعة أقل في تطوير الأشياء ، المزيد من الوقت للتصحيح ، كتابة الاختبارات ، في النهاية - إصدارات أقل تكرارًا) ولكن تقليل كتابة رمز واحد أو كتابة هذا الرمز 1 والتعامل معه جيدًا ... أفضل كتابة رمز واحد مرة أخرى في كل مرة. في النهاية ، أنا لست مساهماً في TS core ولا أرغب بالتأكيد في التعامل مع التعقيد المحتمل لهذا السكر.

انها ليست صفقة يا رفاق. كما يتطلب الأمر الشجاعة والحكمة لتحديد الطلب باعتباره معقدًا للغاية بحيث لا يمكن تنفيذه (مع زيادة التعقيد الكلي للشفرة في النتيجة) ، لذا أهنئكم يا رفاق على تطوير TypeScript وشكراً لكم على عملكم!

(جاء ملاحظة: هنا لتعلم لماذا لا - في النهاية غيرت رأيي وسوف أتعامل مع هذا ._property = ...
وستظل سعيدا)

idchlife لا يتمثل هدف الخاصية set في توفير شرطة سفلية واحدة للمطورين عند تعيين القيمة. قد ترغب أيضًا في إضافة بعض المنطق في عملية set .

يرجى إعادة فتح هذه المشكلة. من الواضح أن هذه ميزة مطلوبة للغاية.

+1 أرغب في إعادة النظر في هذا الأمر.

من الغريب جدًا أن يكون السبب المنطقي هو "هذا من شأنه أن يجعل الأمور مربكة" في حين أن العديد من اللغات الأخرى تفعل ذلك بالفعل.

نظرًا لأن جميع s لا يفعلون الكثير ، فسأقوم بإرسال بريد عشوائي بتعليق آخر.

سيكون هذا سكرًا نحويًا يساعد في جعل الأشياء أكثر قابلية للقراءة وسرعة التنفيذ. تحتوي الكثير من اللغات على سكر نحوي بما في ذلك الكتابة المطبوعة. لا يبدو أن هناك أي سبب وجيه حقيقي لعدم القيام بذلك ، كما أن التعقيد الشديد لا يمثل أبدًا سببًا جيدًا لعدم القيام بشيء ما ، بل هو أكثر من عملية تهجئة كسولة. يعد حل المشكلات المعقدة للغاية أحد الأسباب التي تجعل معظم الناس ينجذبون إلى هندسة البرمجيات. لذا خذ هذه المسألة المعقدة وحلها بطريقة لطيفة وليست معقدة. هل سيتطلب إعادة هيكلة وتغييرات محفوفة بالمخاطر؟ ربما ولكن هذه هي الطريقة التي تتم بها الأمور.

لا يزال مرغوبًا فيه. لا تواجه اللغات الأخرى مشكلة في دعم الرؤية المختلفة لوظيفة get- and set-. لإضافة ضرر إلى الإهانة ، تم إنشاء Typescript بواسطة Microsoft ، تمامًا مثل C # ، لكن الأخير يدعمها تمامًا:

public string myPropertyWithLimitedAccess { get; private set; }   

انظر إلى ذلك. سهل القراءة بشكل جميل ، ولا يوجد شيء معقد على الإطلاق.

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/auto-implemented-properties

ليس هناك سبب وجيه لعدم دعم:

private _myProperty: string;

public get myProperty(): string { return this._myProperty; }
private set myProperty(value: string) { this._myProperty = value; }

نقاط المكافأة في قرارات التصميم الغريبة ، لأن Typescript صُنعت أساسًا لمطوري .NET ليعتادوا أكثر على العمل مع الواجهة الأمامية للمتصفح.

+1
من المؤكد أن المطبوع سيستفيد من هذه الوظيفة!

يعد TypeScript رائعًا حتى بعد C # ، لكن هذا القيد الذي لا طائل من ورائه يزعجني كثيرًا. يرجى إعادة فتحه.

من شأنه أن يزيد من تعقيد اللغة

هل هذا حقًا معقد مقارنة بأشياء مثل readonly [P in keyof T]: T[P] ؟

صدم. الكل يريد هذه الميزة. ألا يجب على مجتمع TypesScript اتخاذ القرار؟

من شأنه أن يزيد من تعقيد اللغة

هل هذا حقًا معقد مقارنة بأشياء مثل readonly [P in keyof T]: T[P] ؟

يأتي التعقيد دورًا في تفاعل ميزات اللغة الأخرى. لسوء الحظ لا يمكنني العثور عليه ، لكن IIRC RyanCavanaugh قدم مثالاً حيث يمكن أن تسمح لك هذه الميزة بإعداد الثوابت ثم انتهاكها عبر الوراثة باستخدام تعبير فئة. فقط لأنه من السهل كتابة تصريح معين ، فهذا لا يعني أنه سيكون من السهل دائمًا التفكير في كيفية تأثيره على الأشياء.

السؤال هو ما هي المشاكل التي ستحلها ميزة معينة ، وأيها ستنشأ. من السهل الإجابة على السؤال الأول ، ومن الصعب الإجابة على الأخير بشكل مفاجئ. لسوء الحظ ، يبدو أن فريق TS يستجيب أحيانًا بـ "تعقيد OMG" بدلاً من توضيح المشكلة. (لكي نكون منصفين ، كلما زاد الوقت الذي يقضونه في الإجابة على الاستعلام x للمرة التاسعة ، قل الوقت الذي يتعين عليهم تطويره.)

لا أتفق بنسبة 100٪ مع فكرة "ألا يجب أن يتخذ المجتمع قرارًا" ، لأنه إذا كان هناك إجماع بين الخبراء الذين يطورون اللغة فعليًا ، فيجب أن يخبرك هذا بشيء. لكنني أعتقد أنه مع وجود شيء مطلوب مثل هذا ، فإن التفسير المدروس من الفريق حول ماهية المقايضة ولماذا يعارضونها ليس كثيرًا لطلبه.

وشخصيًا ، أعتقد أن المقايضة تساوي 1000٪ في هذه الحالة. ولكن إذا كنت لا أستطيع أن أزعجني لتحديدها وجعلها تعمل ، أفترض أنه ليس لدي الكثير من الحق في تقديم شكوى.

هل هذا هو الوقت المناسب لإعادة النظر في هذه القضية؟

يعد المُعدِّل readonly رائعًا ، ولكن هناك العديد من الحالات التي تريد أن تكون فيها قادرًا على تغيير القيمة داخل الفصل مع الاحتفاظ بكل شيء للقراءة فقط من الخارج.

غالبًا ما أختار عدم إنشاء الخاصية readonly لأنني لا أحب الضوضاء التي يضيفها حقل الدعم الخاص + الخصائص.

سيكون من الرائع لو كان هناك بعض السكر النحوي للقيام بذلك نيابة عنك. شيء مثل:

// Option 1: C# style
public name: string { get; private set; }

// Option 2: Swift style
private(set) name: string

// Option 3: Swift struct-style
public readonly name: string

mutating changeName(name: string) {
  this.name = name
}

// Option 4: New keyword
public frozen name1: string
public readonly name2: string

أنا أحب الخيار 2 ، imo سيكون مناسبًا تمامًا للغة TypeScript.

باستخدام الخيار 3 ، يمكنك فقط تغيير الحقول للقراءة فقط في الوظائف التي تم وضع علامة عليها كـ mutating

باستخدام الخيار 4 ، لا يمكن تعيين frozen إلا في المُنشئ ، ويمكن تعيين readonly داخل هذه الفئة ، وليس بواسطة أي فئات أو فئات خارجية موروثة من هذه الفئة.

كمرجع ، أفكار yvbeek حول المعدلات الأكثر مرونة هي الأنسب للمناقشة في https://github.com/microsoft/TypeScript/issues/37487.

هذه المشكلات مخصصة للمشتركين والمحددين ، ولديها عدد كبير جدًا من الأصوات المؤيدة! أعتقد أنه سيكون من المفيد إعطاء محرِّكات ومحددات معدِّلات وصول مختلفة (ويمكننا تحديث المجموعة الحالية من المعدِّلات في # 37487 إذا قرر فريق TypeScript أن يكون شيئًا مقبولًا للمضي قدمًا به)

لا أتفق بنسبة 100٪ مع فكرة "ألا يجب أن يتخذ المجتمع قرارًا" ، لأنه إذا كان هناك إجماع بين الخبراء الذين يطورون اللغة فعليًا ، فيجب أن يخبرك هذا بشيء. لكنني أعتقد أنه مع وجود شيء مطلوب مثل هذا ، فإن التفسير المدروس من الفريق حول ماهية المقايضة ولماذا يعارضونها ليس كثيرًا لطلبه.

snarfblam لا تسد هذا الموضوع بتعليق غير ذي صلة ، لكنني أعتقد أنك كشفت عن مبدأ أساسي للطريقة التي يجب أن تعمل بها الحكومة.

عدم وجود هذه الميزة هو ألم حقيقي بالنسبة لي و (من بين أمور أخرى) جعلني أتحول من TS / NodeJS إلى شيء أكثر ... اكتب آمن. كل شيء على ما يرام ورائع ، ولكن عندما تعمل في مشروع معقد به الكثير من هياكل البيانات (متداخلة بعمق عدة مرات) ولا يمكنك نمذجة البيانات بشكل صحيح ، فإنك تشعر بأن هذه ليست لغة " أولاد".

في حالتي الخاصة ، أريد أن تكون الخاصية للقراءة فقط ، ولكن قابلة للتعديل من الداخل ... وأيضًا مسلسلة إلى JSON. الكثير من الأطواق للقفز من خلالها.

قد تتبع هذه الميزة نفس مسار _السلسلة الاختيارية_. سيطلب الناس هذه الميزة لسنوات ثم في النهاية ستتم إضافتها إلى اللغة ، لأنها عملية وتقدم اللغات الأخرى نفس الميزة.

بخلاف ذلك ، آمل أن تصبح بعض عمليات التنفيذ جزءًا من EcmaScript ثم تشق طريقها إلى TypeScript.

لقد تحولت مؤخرًا إلى الكتابة المطبوعة وكنت أحب اللغة. أشعر بالصدمة حقًا لأن هذه الميزة العملية الموجودة في لغات أخرى لم يتم تنفيذها هنا. يرجى إعادة النظر في إضافته في إصدار مستقبلي بغض النظر عن مدى التعقيد الذي تعتقد أنه قد يضيفه إلى اللغة.

لقد حققت شيئًا مشابهًا لـ c # بأحرف بهذه الطريقة:

export class I18nService {
  private static ref: I18nService;

  public static get instance(): I18nService {
    if (!I18nService.ref) {
      I18nService.ref = new I18nService();
    }

    return I18nService.ref;
  }
}

أخطاء الكتابة مثل ما يلي سهلة الفهم وليست معقدة:

Property 'foo' is writable only in protected scope within class 'Blah' and its subclasses.

أو

Property 'foo' is readable only in protected scope within class 'Blah' and its subclasses.

إلخ ، وما شابه ذلك مع private .

هذا بصراحة ليس معقدًا.

راجع للشغل ، لقد عثرت على هذه المشكلة بالصدفة أيضًا ، وأنا أستخدم هذا النوع من "الاختراق" في هذه الأثناء:

// somewhere.ts
declare global {
    type Writable<T> = { -readonly [P in keyof T]: T[P]; }
}

// example.ts
class Example {

    public readonly prop: number;

    public doSomething(n: number): void {
        (this as Writable<this>).prop = n;
    }
}

من الناحية الفنية ، يمكن استخدام هذا في كل مكان ، ولكن استخدام هذا الحل البديل يجب أن يقتصر على الكود داخل طرق الفصل.

راجع للشغل ، لقد عثرت على هذه المشكلة بالصدفة أيضًا ، وأنا أستخدم هذا النوع من "الاختراق" في هذه الأثناء:

لقد لعبت بهذه الفكرة بنفسي ، لكن المشكلة هي أنه ليس لديك طريقة للتمييز بين خصائص "القراءة العامة فقط" وخصائص القراءة فقط حقًا. هذا يجعله غير مناسب جدًا كحل للأغراض العامة.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات