Typescript: دعم الفصول النهائية (غير subclassable)

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

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

في Java ، لا يمكن تمديد الفئة التي تم وضع علامة عليها بالنهائي ، لذلك باستخدام نفس الكلمة الرئيسية في TypeScript سيبدو كما يلي:

final class foo {
    constructor() {
    }
}

class bar extends foo { // Error: foo is final and cannot be extended
    constructor() {
        super();
    }
}
Suggestion Won't Fix

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

يجب أن يكون هناك أيضًا مُعدِّل final للطرق:

class Foo {
  final fooIt():void{

  }
}

class Bar {
  fooIt():void {

  }
}
// => Method fooIt of Bar cannot override fooIt of Foo, because it is final.

على سبيل المثال ، غالبًا ما أستخدم النمط التالي ، حيث أريد تجنب fooIt بشكل عاجل لتجاوزه:

import Whatever ...

abstract class Foo {
  private ImportantVariable:boolean;

  protected abstract fooIt_inner:Whatever();

  public final fooIt():Whatever() {
    //do somestate change to aprivate member here, which is very crucial for the functionality of every Foo:
    ImportantVariable = true;
    //call the abstract inner functionality:
    return this.fooIt_inner();    
  }
}

ال 124 كومينتر

فئة ذات مُنشئ خاص غير قابلة للتمديد. ضع في اعتبارك استخدام هذا بدلاً من ذلك.

مما تذكرته ، كنت متأكدًا من أن المترجم لم يعجبه الكلمة الأساسية الخاصة في المنشئ. ربما لا أستخدم نسخة اللصق رغم ذلك

هذه ميزة جديدة ، سيتم إصدارها في TS 2.0 ، ولكن يمكنك تجربتها باستخدام typescript@next . راجع https://github.com/Microsoft/TypeScript/pull/6885 لمزيد من التفاصيل.

حسنا شكرا لك

ألا يجعل المُنشئ الخاص أيضًا فصلًا دراسيًا غير قابل للتشغيل خارج الفصل؟ إنها ليست إجابة صحيحة على الدرجة النهائية.

تستخدم Java و / أو C # فئة final لتحسين فصلك في وقت التشغيل ، مع العلم أنها لن تكون متخصصة. أود أن أزعم أن هذا هو القيمة الرئيسية للدعم النهائي. في TypeScript ، لا يوجد شيء يمكننا تقديمه لجعل الكود الخاص بك يعمل بشكل أفضل مما كان عليه بدون نهائي.
ضع في اعتبارك استخدام التعليقات لإبلاغ المستخدمين بالاستخدام الصحيح للفصل ، و / أو عدم الكشف عن الفئات التي تنوي أن تكون نهائية ، وكشف واجهاتهم بدلاً من ذلك.

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

يجب أن يكون هناك أيضًا مُعدِّل final للطرق:

class Foo {
  final fooIt():void{

  }
}

class Bar {
  fooIt():void {

  }
}
// => Method fooIt of Bar cannot override fooIt of Foo, because it is final.

على سبيل المثال ، غالبًا ما أستخدم النمط التالي ، حيث أريد تجنب fooIt بشكل عاجل لتجاوزه:

import Whatever ...

abstract class Foo {
  private ImportantVariable:boolean;

  protected abstract fooIt_inner:Whatever();

  public final fooIt():Whatever() {
    //do somestate change to aprivate member here, which is very crucial for the functionality of every Foo:
    ImportantVariable = true;
    //call the abstract inner functionality:
    return this.fooIt_inner();    
  }
}

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

لم يتم قفل المشكلة للسماح لأعضاء المجتمع بمواصلة إضافة التعليقات. مع وجود ملاحظات كافية وحالات استخدام مقنعة ، يمكن إعادة فتح المشكلات.

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

في TypeScript ، لا يوجد شيء يمكننا تقديمه لجعل الكود الخاص بك يعمل بشكل أفضل مما كان عليه بدون نهائي.

نجاح باهر ، ارتد! لا تجعل الأنواع الثابتة شفرتك تعمل بشكل أفضل أيضًا ، لكن الأمان هو شيء جميل.

النهائي (مغلق) موجود هناك مباشرةً مع تجاوز كميزات أود رؤيتها لجعل تخصيصات الفصل أكثر أمانًا. لا يهمني الأداء.

لا تجعل الأنواع الثابتة شفرتك تعمل بشكل أفضل أيضًا ، لكن الأمان هو شيء جميل.

بالضبط. تمامًا كما يمنع private الآخرين من استدعاء الطريقة ، فإن final يقيد الآخرين من تجاوز الطريقة.

كلاهما جزء من واجهة OO للفصل مع العالم الخارجي.

أتفق تمامًا مع pauldraper وmindarelus. الرجاء تنفيذ هذا ، سيكون هذا منطقيًا جدًا لأنني أفتقده حاليًا.

لا أعتقد أن النهائي مفيد للأداء فقط ، إنه مفيد أيضًا للتصميم ولكن لا أعتقد أنه منطقي في TypeScript على الإطلاق. أعتقد أنه تم حل هذا بشكل أفضل من خلال تتبع تأثيرات التغيير لـ Object.freeze و Object.seal .

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

إن فكرة استخدام final على فئة أو طريقة فئة في جافا لها علاقة أكبر بتقليل قابلية تغيير الكائن لأمان مؤشر الترابط في رأيي. (البند 15. جوشوا بلوخ ، جافا الفعالة)

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

أود حقًا أن أرى هذا مطبقًا. أعتقد أنه سيساعد في إنشاء كود أكثر قوة. الآن ... كيف يُترجم ذلك إلى JS ، ربما لا يتعين عليه ذلك بصراحة. يمكن أن يبقى فقط على الجانب المطبوع على الكتابة من السياج حيث يكون باقي فحص وقت الترجمة.

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

بالنسبة لي ، سيلعب final نفس الدور في الكتابة المطبوعة مثل private أو الكتابة ، وهذا هو عقد الكود. يمكن استخدامها لضمان عدم كسر عقد الرمز الخاص بك. أود ذلك كثيرا.

@ hk0i تم ذكره أيضًا في البند 17 (الإصدار الثاني) بطريقة مشابهة لما تم ترديده هنا:

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

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

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

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

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

مثل العديد من الأشخاص في هذا الموضوع ، سأصوت لأتمكن من ختم الفصل.

mhegazy لدى المنشئين الخاصين والفصول المختومة / النهائية دلالات مختلفة تمامًا. بالتأكيد ، يمكنني منع الامتداد من خلال تحديد مُنشئ خاص ، ولكن بعد ذلك لا يمكنني أيضًا استدعاء المُنشئ من خارج الفصل ، مما يعني أنني بحاجة بعد ذلك إلى تحديد دالة ثابتة للسماح بإنشاء مثيلات.

أنا شخصياً أدعو إلى إجراء فحوصات مختومة / نهائية للمترجم للتأكد من أن الفئات والطرق التي تم تمييزها بمختوم / نهائي لا يمكن تمديدها أو تجاوزها.

في سياق مشكلتي ، أريد أن أكون قادرًا على الحصول على مُنشئ عام حتى أتمكن من إنشاء مثيل للكائن ، ولكن أمنع امتداد الفئة ، ولن يسمح بذلك إلا بإضافة مختوم / نهائي.

هناك مهمة - كتابة رمز ذلك

  • تعمل الأشياء الثابتة
  • هو الميراث مجانا
  • طرق انعكاس مجانية

وكلمة رئيسية final ضرورية هنا ، IMHO.

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

zigszigsdk بما أن الأساليب لا يتم تجاوزها أبدًا ، كيف يعمل هذا؟

مقابل final :
بنفس الطريقة التي تعمل بها الآن ، باستثناء أن المترجم سيشتكي إذا أخفى أحد طريقة سوبر -التي تم إعلانها نهائية- من سياق this .

مقابل override :
بنفس الطريقة التي تعمل بها الآن ، باستثناء أن المترجم سيشتكي إذا أعلن أحدهم عن طريقة override ، ولم يكن لدى super الخاص به طريقة بهذا الاسم ، أو أنه يحتوي على طريقة ولكن تم الإعلان عنها على أنها final .
من المحتمل أيضًا أن يحذرك إذا قمت بإخفاء طريقة السوبر من سياق this ولم تذكر التجاوز.

تستخدم Java و / أو C # الفئة النهائية لتحسين فصلك الدراسي في وقت التشغيل ، مع العلم أنه لن يكون متخصصًا. أود أن أزعم أن هذا هو القيمة الرئيسية للدعم النهائي.

mhegazy ليس تماما! وظيفة أخرى مهمة هي أن تكون واضحًا بشأن أي أجزاء من الفصل يتوقع تجاوزها.

على سبيل المثال ، راجع العنصر 17 في "Java فعال": "التصميم والمستند للإرث أو حظره":

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

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

أعتقد أن الفصول والأساليب final مهمة جدًا. أتمنى أن تنفذها.

حالة مستخدم مقنعة أخرى mhegazy . لقد تعلمت اليوم نمط أسلوب القالب ، ووجدت أن final مطلوب لمنع الفئات الفرعية من تغيير طريقة القالب كما يقول نموذج أسلوب النموذج في ويكيبيديا . لكن لا يمكنني القيام بذلك في TypeScript الجميلة الخاصة بي. يا للأسف!

يتيح نمط القالب للفئات الفرعية إعادة تعريف خطوات معينة للخوارزمية دون تغيير بنية الخوارزمية

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

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

أود أن أرى إعادة فتح هذه المشكلة وتنفيذها.

عند إنشاء مكتبة ستستخدمها داخليًا أو تشاركها بشكل عام (على سبيل المثال في npm) ، فأنت لا تريد أن يضطر أولئك الذين يستخدمونها إلى تصفح الكود والبحث في التعليقات أو المستندات لمعرفة ما إذا كان الفصل يستطيع / يستطيع لا يمكن الكتابة عليها. إذا قاموا بالكتابة عليه ، فإن ذلك يؤدي إلى حدوث خطأ.

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

5 سنتات حول هذا الموضوع هي أنه يجب إعادة فتح هذا وتنفيذه.

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

أنا أيضًا أصوت لإعادة الفتح ، مع دعم كل من الفصول والأساليب

لا أقول إنه لا ينبغي أن أكون غير متأكد من كيفية عمل نمط الكلمة الرئيسية النهائية في سياق الكتابة المطبوعة؟

ألن تمنع الكلمة الأساسية النهائية المستخدمين / المبرمجين من تجاوز / وراثة الفئة / الطريقة المذكورة؟

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

niokasgami Freeze مرتبط بـ [data] (https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Object/freeze)
ومتوفر بالفعل كجزء من ES6. ينطبق النهائي على الفئات والطرق (يمكن أن يكون المتغير للقراءة فقط وبالتالي يكون بمثابة "نهائي" حيث لا يمكننا تجاوز المتغير الفائق).

يتم استخدام الكلمة الأساسية "النهائية" في JAVA حيث تكون مختومة في C # .

نظرًا لأن الكتابة المطبوعة مستوحاة بشدة من C # ، يجب أن يكون هناك احتمال أكبر بأن يكون "مختوم" هو الخيار المختار. الآن ، من المحتمل أن يكون لدينا ارتباك مع ختم ES6 الذي يختم الكائن في وقت التشغيل؟

Xample أعتقد أنه يمكنك أيضًا استخدام الصيغة النهائية في المتغيرات المحلية في Java. أتذكر أنني اضطررت إلى القيام بذلك عندما كنت أكتب تطبيق Android. أعتقد أنه تطلب مني القيام بذلك مع حدث لكنني لست متأكدًا بنسبة 100٪.

function(){
    let final myVariable = 'Awesome!'
    document.addEventListener('scroll', e => {
        console.log(myVariable)
        myVariable = 'Not Awesome' // Throws an error
    })
}

TheColorRed حسنًا ، المتغير المحلي النهائي في Java يعني ثابتًا ، أليس كذلك؟

EternalPhane أعتقد ذلك ، لقد استخدمت دائمًا const في نطاق مثل عالمي ... لم أفكر مطلقًا في استخدامه ضمن وظيفة أو طريقة ... أعتقد أن التعليق السابق باطل إذن ...

Xample ، نعم ، أرى وجهة نظرك لـ Sealed from C # ، إنها لا تعمل بنفس الطريقة بصراحة في رأيي ، كلاهما لا يمكن حقًا الدخول إلى الفئة نظرًا لأن كلاهما يمكن أن يكون مربكًا (مغلقًا للختم وما إلى ذلك) ونهائي نحن غير متأكدين كيفية تطبيقه لأنه يستخدم في Java باعتباره ثابتًا: /

في جافا يمكنك final أي متغير أو طريقة أو فئة. بالنسبة للمتغيرات ، فهذا يعني أنه لا يمكن إعادة تعيين المراجع (بالنسبة للأنواع غير المرجعية ، يعني هذا أنه لا يمكنك تغيير قيمها أيضًا). بالنسبة للفصول ، فهذا يعني عدم وجود امتدادات ( extends ... كلمة رئيسية). بالنسبة للطرق ، فهذا يعني عدم تجاوز الفئات الفرعية.

الأسباب الرئيسية لـ final في جافا:

  • تقليل ثبات المتغيرات: من أجل سلامة الخيط
  • إنهاء الفصول حتى لا يمكن توريثها: يفرض التركيب على الميراث لأن الوراثة معقدة بطبيعتها عندما تبدأ الفئات الفرعية الخاصة بك في استدعاء الطرق الفائقة عن غير قصد
  • يمنع حدوث أخطاء برمجية بسيطة: إذا لم تكن لديك نية لتغيير قيمة ما ، فالأخبار الجيدة لم تعد ممكنة
  • يستخدم لما يعتقده معظم الناس عندما يتخيلون الثوابت: قيم قابلة لإعادة الاستخدام ستراها في كل مكان ، كما هو الحال في public static final String KEY = "someStringKeyPathHere" ، وهي مفيدة لتقليل الأخطاء ولكن لها فائدة إضافية في وقت التجميع تتمثل في عدم إعادة إنشاء كائنات سلسلة متعددة لنفس القيمة

ربما تركت حالتين من حالات الاستخدام ، لكنني كنت أحاول إبقائها عامة جدًا وإعطاء بعض الأمثلة.

يتطلب @ TheColorRed Android ذلك عندما تعلن عن متغير خارج رد

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

أعتقد بشكل واقعي على الرغم من أنه يمكنك إعطاء صفعة على معصمك لبعض هذه الفوائد ، إلا أنك لا تحصل على أي من الفوائد الحقيقية لـ java-esque final بمجرد تحويلها إلى js.

@ hk0i أعتقد أنني أستطيع أن أفهم وجهة نظرك ولكن بشكل عام أوافق

أود أن أقول إن معظم الشفرات في الكتابة المطبوعة هي لغرض التصحيح / التتبع لمساعدة المبرمج على القيام برمز "نظيف" جيدًا (من فضلك لا تقتبس لي من أنني أعرف أن لديهم بعض أكواد السباغيتي المطبوعة هنا ههههه)

لا يتم نقل معظم ميزات النص المطبوع في معظم الأوقات عند تحويلها إلى JS لأنها غير موجودة في JS.

على الرغم من أنه عند وقت التشغيل / كتابة الكود الخاص بك ، فإنه من المفيد رؤية الخطأ في التعليمات البرمجية الخاصة بك وتتبعها بسهولة أكبر من مع JS (وقد يكون من الصعب تتبع الأخطاء في HECK JS)

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

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

@ hk0i لا أوافق على ذلك ، والغرض من الكتابة المطبوعة هو هيكلة الكود وبالتالي توفير الأدوات اللازمة للقيام بذلك. لا يتعين علينا استخدام الصيغة النهائية في Java ، فنحن نستخدمها عادةً عندما نعلم أن توسيع فئة أو طريقة قد يؤدي إلى ظهور آثار جانبية (أو لأي سبب آخر يتعلق بالسلامة).

الاعتماد على حلول ES6 الحالية إضافة فحص قابلية التشغيل لوقت التشغيل (مثل استخدام Object.seal أو Object.freeze) يجعلك تفقد فائدة وجود أخطاء مباشرة عند كتابة الكود الخاص بك (على الرغم من أنه يمكن القيام به بسهولة باستخدام هذا المصمم ).

TheColorRed نعم… وفي الكتابة المطبوعة لدينا تمييز بين المتغير المحلي ومتغير الفئة.

  • readonly لمتغير فئة
  • const : لأي متغير آخر

لن يكون أي منهم دقيقًا بالنسبة للطريقة أو الفصل. لا يعني تجاوز طريقة ما أننا نعيد تعريفها (فكر في الأساليب الافتراضية في C ++) ، فنحن فقط نعرّف الطريقة التي سيتم استدعاؤها بشكل أساسي قبل الطريقة الممتازة (والتي يمكننا تسميتها باستخدام super ).

niokasgami ربما لا تكون التسمية مشكلة حقًا لأننا ما زلنا نفهم أن Object.seal ينطبق على ... كائن أثناء إغلاق فئة وطريقة على الهيكل نفسه.

TL ؛ DR:

  • سيكون منع الامتدادات اسمًا واضحًا جيدًا لمنع توسيع الفئات
  • سيكون PreventionOverrides اسم مرشح جيد لمنع تجاوز الفئات
    ولكن: يستخدم seal على نطاق واسع في C # ، وهو أقصر وله نفس السلوك المتوقع.

بالمناسبة نسيت أن أذكر أن هناك أيضًا Object.preventExtensions()
يمكن رؤية الاختلافات

قراءة

  • ممكن دائما ... من يريد كتابة متغير فقط؟

التحديث والحذف

  • منع إعادة تعريف حذف متغير: للقراءة فقط لعضو الفصل ، const (لأي شخص آخر)
  • منع إعادة تعريف الطريقة: لا شيء يمنعك من القيام بذلك (ضمن طريقة الصنف) this.aMethod = ()=>{} . هل يجب أن تكون الأساليب readonly أيضًا لمنع مثل هذه الاختراقات؟ نفس الشيء مقابل delete this.aMethod

خلق

  • ينطبق فقط على الكائن أو كما نتحدث هنا عن البنية: class حيث أن الفئة تعرف أعضاء الكائن ، فإن الكتابة المطبوعة تمنع ضمنيًا بالفعل من إنشاء خصائص جديدة أثناء التنقل ... على سبيل المثال this.unKnownProperty = "something" ts سيتم رفع خطأ وقت التحويل TS2339 كما هو متوقع.

تمتد

  • ينطبق فقط على الفئات ، ونحن لا نفعل أي شيء على الكائن نفسه حتى الآن ... (على عكس الإنشاء في وقت التشغيل). هذا هو المكان الذي سيكون فيه final أو seal مناسبًا. السؤال هو كيف تحافظ على ثباتك مع التجميد والختم و preventExtensions من ES6؟ (إذا كان علينا).
    تمديد فصل ، يعني أننا نمنع إنشاء فصل آخر من هذا الفصل. يمكننا بعد ذلك قراءته ولكن لا يمكننا حذفه (من قام بحذف الفصل على أي حال). السؤال ليس عمود "التحديث". هل فئة final قابلة للتحديث؟ ما هي فئة قابلة للتحديث؟ تخميني هو نعم ... ولكن بعد ذلك سيكون التحديث لتنفيذ هذه الفئة (فهم واجهة الفصل)؟ يجب أن يكون تنفيذ فصل آخر ممكنًا دائمًا ... لكنه لا يتعلق بتحديث الفصل الأول. حسنًا ... ربما جاءوا ببساطة إلى نفس الأسئلة بكتابة c # وقرروا أن seal كانت الكلمة الأساسية الجيدة.

تجاوز

  • منع تجاوز الطريقة الحالية في فئة موسعة. مرة أخرى ، نحن لا نكتب فوق أي شيء حتى الآن لأننا نتحدث عن تعريف (طريقة داخل الفصل). لذا منع الإنشاء ، والسماح بالقراءة ، والسماح بالتحديث (يمكننا منع تحديث الطريقة أو حذفها باستخدام القراءة فقط إذا كانت قابلة للتطبيق على الطرق أيضًا). أفضل تسمية؟ preventOverrides ؟ أو مرة أخرى seal كما هو مستخدم في C #

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

لا تفهموني خطأ ، أنا لست ضد هذا. أنا كثيرا من أجل ذلك. أنا أحاول فقط أن أتخبط وراء عقلية Microsoft المتناقضة حول سبب عدم وجوب أن تكون ميزة ، والتي تقول بشكل أساسي أنه نظرًا لأنها ليست ميزة JavaScript ، فلا يمكن أن تكون ميزة TypeScript.

... إذا كنت أفهم بشكل صحيح.

@ hk0i Generics ، للقراءة فقط ، والعديد من الميزات الأخرى ليست من ميزات JavaScript ، لكنها لا تزال مضافة إلى TypeScript ، لذلك لا أعتقد أن هذا هو السبب ...

تبتعد TypeScript فقط عن الميزات التي تتطلب إنشاء تعليمات برمجية بطريقة غير مباشرة. تعتبر العوامل العامة ، للقراءة فقط ، وما إلى ذلك ، مفاهيم وقت التجميع البحتة والتي يمكن محوها ببساطة لإنتاج المخرجات التي تم إنشاؤها ، لذا فهي لعبة عادلة.

يمكن "محو" final في وقت الترجمة أيضًا ، فلماذا لا يجعلها ذلك "لعبة عادلة"؟

🤷‍♂️

TheColorRed أعتقد أن هذا أكثر أو أقل هذا إما أن لديهم أولوية أخرى للتكامل.
أو أنهم غير متأكدين من مدى إمكانية التنبؤ بهذه الكلمة الرئيسية الجديدة يمكن أن تعمل في وقت التجميع / الترميز. إذا فكرت في الأمر ، فإن تصميم الكلمة الرئيسية النهائية يمكن أن يكون غامضًا للغاية. النهائي يمكن أن تستخدم الكثير لأغراض كثيرة. كما ترى من وثائق Jsdoc ، يمكنك استخدام العلامة "final" التي تخبر مترجم jsdoc أن هذا المتغير مجمد وبالتالي للقراءة فقط.

هنا تصادم التصميم. يمكن تطبيق Readonly على المتغير و getter إذا تذكرت أيهما "أدى إلى تجميد" المتغير وجعله للقراءة فقط والأخير يجعله نهائيًا وبالتالي للقراءة فقط أيضًا.

يمكن أن يتسبب هذا في إرباك المبرمج الذي لا يعرف ما إذا كان يجب عليه وضع علامة على متغيراته بشكل نهائي أم للقراءة فقط.

ما لم نحتفظ بهذه الكلمة الرئيسية حصريًا لإعلانات الفصل والطريقة ، أعتقد أن السلوك أو النهائي سيتعارض مع القراءة فقط.

أعتقد أنه بدلاً من الختم (الذي يمكن أن يتعارض مع object.seal) أو النهائي (الذي يتعارض تصميم هذا الغرض مع الكلمة الأساسية للقراءة فقط) ، يمكننا أن نختار طريقة أكثر "مباشرة" لتسميتها وتصميمها.

لاحظ أن هذه الفكرة هي "فكرة" لسلوك مشابه ولكن في نفس الوقت يختلف عن سلوك C #؟ لقد أخذت بعض الإلهام من كيف أن C # عادة غير قابلة للإصلاح ومن ثم عليك أن تقول أن هذه الطريقة افتراضية.

`مثال مساحة الاسم {

export class myClass {

    constructor(){}

    // Make the func non ovveridable by inheritance. 
    public unoveridable myMethod(){

    }

    public myMethodB(){

    }
}

export class MyClassB extends myClass {

    // Nope not working will throw an error of an nonOverridable error
    myMethod(){
        super.myMethod();
    }

    // Nope will not work since unoverridable.
    myMethod(){

    }

    // Design could be implemented differently since this could complicate  ¸
    // the pattern of typescript
    public forceoverride myMethod(){
      // destroy previous pattern and ignore the parent method thus a true ovveride
    }

    // Yup will work since it's still "virtual".
    myMethodB(){
        super.myMethodB();
    }
}
// Can extend an existing Parent class
// Declaring an unextendable class make all is component / func nonOverridable by 
// inheritance. (A class component can still be overwritten by prototype usage.)
export unextendable class MyFinalClass extends Parent {

    constructor()

    // nonoverridable by default.
    public MyMethod(){

    }
}
// nope throw error that MyFinalClass is locked and cannot be extended
export class MyChildClass extends MyFinalClass{}

} `

تحرير: لم أقم بتضمين المتغير وحصلت على أنه موجود بالفعل للقراءة فقط.

mhegazy يرجى النظر في إعادة فتح هذه المشكلة. يبدو أن استجابة المجتمع تظهر بشكل كبير بجانب إضافة كلمة رئيسية final ، مثل Java ( final ) ، C # ( sealed ، readonly ) ، PHP ( final ) ، Scala ( final ، sealed ) ، و C ++ ( final ، virtual ). لا يمكنني التفكير في لغة OOP مكتوبة بشكل ثابت لا تحتوي على هذه الميزة ، ولم أسمع حجة مقنعة حول سبب عدم احتياج TS إليها.

bchernymhegazy أتفق تمامًا مع ما ورد أعلاه. لا أستطيع أن أرى أي سبب مقنع جيدًا لماذا لا يمكن أن يكون final مجرد قيد آخر على وقت الترجمة ، مثل معظم السكر النحوي الذي نراه في TypeScript - دعنا نواجه الأمر ، الكتابة الثابتة ، الأدوية العامة ، معدِّلات الوصول ، كتابة الأسماء المستعارة ، واجهات ... كل السكر! أفهم أن فريق TypeScript ربما يرغب في التركيز على أخذ اللغة في اتجاهات أخرى ، ولكن بجدية ، هذا هو OOP 101 ... كان يجب أن يكون هذا منذ وقت طويل ، عندما كان TypeScript لا يزال صغيرًا جدًا!

mhegazy هل لي أن أحيلك مرة أخرى إلى تعليق مبكر

فئة ذات مُنشئ خاص غير قابلة للتمديد. ضع في اعتبارك استخدام هذا بدلاً من ذلك.

في وقت كتابة هذا التعليق تم التصويت عليه بـ 21 مرة.
من الواضح أن هذا ليس ما يريده المجتمع كحل!

لقد تلقيت الكثير من التعليقات حول هذا الأمر. لا أستطيع أن أفهم لماذا لا فائدة في التنفيذ

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

لاحظ أن هذه المشكلة تتعلق بالفصول النهائية / المختومة . كانت هناك مناقشة خارج الموضوع للطرق النهائية / المختومة والتي تعتبر مفهومًا مختلفًا تمامًا.

تم النظر في بعض النقاط عندما استعرضنا هذه المرة الأخيرة

  • الفئات هي ميزة JAVASCRIPT ، وليست ميزة مميزة . إذا كنت تشعر حقًا أن الفصول الدراسية عديمة الفائدة تمامًا بدون final ، فهذا شيء يجب تناوله مع لجنة TC39 أو طرحه للمناقشة. إذا لم يكن هناك من يرغب أو قادر على إقناع TC39 بأن final ميزة لا غنى عنها ، فيمكننا التفكير في إضافتها إلى TypeScript.
  • إذا كان من القانوني استدعاء new على شيء ما ، فإن ذلك يحتوي على مراسلات وقت تشغيل واحد لواحد مع وراثة منه. فكرة الشيء الذي يمكن أن يكون new 'd وليس super ' d فقط غير موجودة في JavaScript
  • نحن نبذل قصارى جهدنا لتجنب تحويل TypeScript إلى حساء الكلمات الرئيسية OOP. هناك العديد من آليات التكوين الأفضل من الميراث في JavaScript ولا نحتاج إلى امتلاك كل كلمة رئيسية واحدة في C # و Java.
  • يمكنك كتابة فحص وقت التشغيل بشكل تافه لاكتشاف الميراث من فصل دراسي "يجب أن يكون نهائيًا" ، وهو ما يجب عليك فعله على أي حال إذا كنت "قلقًا" بشأن شخص يرث عن غير قصد فصلك الدراسي نظرًا لأن جميع المستهلكين قد لا يستخدمون TypeScript .
  • يمكنك كتابة قاعدة نسالة لفرض اصطلاح أسلوبي لم يتم توريث فئات معينة منه
  • السيناريو الذي يرثه شخص ما "عن طريق الخطأ" من الفصل الذي يجب أن يكون مختومًا هو نوع من السيناريو الفردي. أود أن أزعم أيضًا أن التقييم الفردي لشخص ما لما إذا كان من الممكن أن يرث من فئة معينة أم لا هو على الأرجح مشكوك فيه.
  • هناك ثلاثة أسباب أساسية لإغلاق فصل دراسي: الأمان والأداء والنية. اثنان من هؤلاء لا معنى له في TypeScript ، لذلك علينا أن نأخذ في الاعتبار التعقيد مقابل الكسب لشيء يقوم فقط بثلث المهمة التي يقوم بها في أوقات التشغيل الأخرى.

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

لم أسمع حجة مقنعة لماذا لا تحتاجها TS

مجرد تذكير بأن هذه ليست الطريقة التي يعمل بها. تبدأ جميع الميزات من -100 . من هذا المنصب

في بعض هذه الأسئلة ، تتساءل الأسئلة عن سبب "استبعادنا" أو "استبعادنا" لميزة معينة. تشير هذه الصياغة إلى أننا بدأنا بلغة حالية (C ++ و Java هي الخيارات الشائعة هنا) ، ثم بدأنا في إزالة الميزات حتى وصلنا إلى النقطة التي أحببناها. وعلى الرغم من أنه قد يكون من الصعب على البعض تصديق ذلك ، فهذه ليست الطريقة التي تم تصميم اللغة بها.

لدينا ميزانية معقدة محدودة. كل ما نقوم به يجعل كل ما نقوم به أبطأ بنسبة 0.1٪. عندما تطلب ميزة ، فأنت تطلب أن تصبح كل ميزة أخرى أصعب قليلاً ، وأبطأ قليلاً ، وأقل احتمالاً قليلاً. لا شيء يدخل إلى الباب هنا لأنه يحتوي على Java أو لأنه يحتوي على C # أو لأنه سيكون فقط بضعة أسطر من التعليمات البرمجية أو يمكنك إضافة مفتاح سطر أوامر . تحتاج الميزات إلى دفع تكاليفها وتكاليف عبئها الكامل على المستقبل.

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

تضمين التغريدة

لا أعتقد أن النقطة هنا ، في هذا المنتدى هي .. "استخدام فئات JavaScript بشكل فعال."

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

نحن نبذل قصارى جهدنا لتجنب تحويل TypeScript إلى حساء الكلمات الرئيسية OOP. هناك العديد من ميكانيكا التكوين الأفضل من الميراث في JavaScript ...

مثل عندما تستخدم final لفرض التركيب على الوراثة في (أدخل ليس اسم اللغة المطبوعة هنا) 😈
(آسف ، لم أستطع المقاومة)

ولكن الأهم من ذلك ، يبدو أن TS تنوي في الغالب أن تكون طبقة توافق لتقديم "JavaScript اليوم الآن" أو شيء من هذا القبيل (a la Babel) باستثناء أنها تضيف بعض التحقق الإضافي من النوع.

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

أعلم أن Kotlin يمكنها الترجمة إلى JS ولديها الكثير من الميزات التي أعتقد أن الناس هنا سيستمتعون بها ، وهذا شيء قد يكون مفيدًا للنظر فيه. أعتقد أنها تضيف بعض مكتبات JS كتبعية رغم ذلك (لم أجربها بنفسي).

الخلاصة الرئيسية هي أنه إذا لم تكن راضيًا عن TypeScript ، فلا تستخدمه.

تضمين التغريدة

حول النقاط التي أثرتها أعلاه ...

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

لقد كنت أتابع TypeScript منذ 0.7 وفي ذلك الوقت ، كانت IIRC تستهدف ES3-ES5. كانت الفئات بالتأكيد إحدى ميزات TypeScript في ذلك الوقت. تنطبق نفس الحجة على المصممين - فهم موجودون في بطاقات ES ، لكنهم موجودون بالفعل في TypeScript كميزة تجريبية.

كمجتمع ، نحن لا نجادل في أن مترجم TypeScript يجب أن يصدر بطريقة ما فئة JavaScript وهي final . سيكون فحص وقت الترجمة كافياً ، بنفس الطريقة التي تكفي بها عمليات التحقق من وقت التجميع لمعدلات الوصول ؛ بعد كل شيء ، فهي ليست ميزات JavaScript أيضًا ، لكن TypeScript لا يزال يجعلها ممكنة.

إذا أصبح final ميزة ES ، فمن المفترض أنه يمكنك إعادة تشكيل هذا الجزء من الباعث عند استهداف ES * لإخراج final مناسب (في نفس ما فعلته للفئات ، عندما تم تقديمها في ES6)؟

إذا كان من القانوني استدعاء new على شيء ما ، فإن ذلك يحتوي على مراسلات وقت تشغيل واحد لواحد مع وراثة منه. فكرة الشيء الذي يمكن أن يكون new 'd وليس super ' d فقط غير موجودة في JavaScript

مرة أخرى ، لا أعتقد أن المجتمع يتوقع منك سحر شيء ما هنا لفرض final في وقت التشغيل. كما ذكرت بدقة ، "غير موجود في JavaScript" ، ولكن كما ذكرنا ، يكفي تقييد وقت الترجمة.

نحن نبذل قصارى جهدنا لتجنب تحويل TypeScript إلى حساء الكلمات الرئيسية OOP. هناك العديد من آليات التكوين الأفضل من الميراث في JavaScript ولا نحتاج إلى امتلاك كل كلمة رئيسية واحدة في C # و Java.

إنها عبارة معروفة إلى حد ما في مجتمع تطوير البرمجيات ككل: "تفضيل التكوين على الميراث" ، لكن "صالح" لا يعني عدم استخدام الوراثة كتعبير شامل. بالتأكيد ، لا _ تحتاج_ إلى كل كلمة رئيسية منفردة في C # و Java ، ولكن يجب أن يكون لديك سبب منطقي للسماح بفصول abstract (والتي بالمناسبة "غير موجودة في JavaScript") ، فلماذا لا فصول final ؟

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

يمكن قول الشيء نفسه بالنسبة لـ C # و Java ، لكنني لست بحاجة إلى فحوصات وقت التشغيل لأن لدي sealed و final للقيام بذلك من أجلي على مستوى المحول البرمجي.

إذا لم يكن كل عملائي يستخدمون TypeScript ، فسيكون لدي الكثير مما يدعو للقلق أكثر من مجرد الوراثة من فئة final ؛ على سبيل المثال ، الوصول إلى أعضاء private أو protected ، لا يوجد فحص ثابت للنوع ، أو القدرة على إنشاء فئة abstract .

هل يجب أن تكون الكود الخاص بنا مليئًا بفحوصات وقت التشغيل لكل هذه الأشياء (التي قد لا يمكنني إضافتها لبعضها) فقط للتأكد من أن المستهلكين الذين لا يستخدمون TypeScript في أمان قدر الإمكان؟

يمكنك كتابة قاعدة نسالة لفرض اصطلاح أسلوبي لم يتم توريث فئات معينة منه

هذا يعني أن كل من يستهلك الكود الخاص بك يقوم بتشغيل linter ، لذلك لا يزال هذا ليس حلاً مناسبًا حقًا ؛ إنه حل بديل.

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

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

عند طرح سؤال يبدأ به ، هل يمكنني عادةً الحصول على إجابة أكثر تحديدًا من الأسئلة التي يجب أن أبدأ بها .

هناك ثلاثة أسباب أساسية لإغلاق فصل دراسي: الأمان والأداء والنية. اثنان من هؤلاء لا معنى له في TypeScript ، لذلك علينا أن نأخذ في الاعتبار التعقيد مقابل الكسب لشيء يقوم فقط بثلث المهمة التي يقوم بها في أوقات التشغيل الأخرى.

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

لا أعتقد أن عدم وجود final يضر بقدرتي على استخدام فئات JavaScript بشكل فعال ، ولا يمكن استخدام فئات JavaScript بدونها. أشعر أن final هو جانب ميزة "من الجيد أن يكون لديك" ، وليس ميزة "ضرورية" ، ولكن بعد ذلك يمكن قول الشيء نفسه بالنسبة للعديد من ميزات TypeScript.

أعتقد أن المشكلة الرئيسية هنا هي أن TypeScript يسمح لنا بإنشاء فئات abstract و _ open_ ، لكن من حيث الميراث وتعدد الأشكال ، لا يسمح لنا برسم صورة كاملة بطريقة أنيقة ومعبرة.

إخفاء المُنشئ ليس ما يريده المجتمع لأن هذا يأخذ القيمة الدلالية والتعبيرية بعيدًا عن تطبيقات الفصل ، ومرة ​​أخرى ، نظرًا لأن مُعدِّلات الوصول هي "شيء رائع" ، لا يمكن حتى فرض هذا في وقت التشغيل ؛ في الأساس حالة "غير موجود في JavaScript".

كمطور لدي العديد من القبعات. في الوقت الحالي لدي قبعة C # وقبعة Kotlin وقبعة TypeScript.

  • مع قبعة Kotlin الخاصة بي ، لا داعي للقلق بشأن final لأن الفصول نهائية بشكل افتراضي.
  • باستخدام قبعة C # الخاصة بي ، أقوم بتطبيق sealed كمسألة عادة ، مما أجبر المستهلكين على أن يسألوا ينبغي . في كثير من الأحيان ، يجب أن تكون فصول C # في الواقع sealed وغالبًا ما يتم تجاهلها.
  • عند تشغيل قبعة TypeScript الخاصة بي ، يجب أن أخفي المُنشئ كحل بديل ، لأنه في رأيي (والمجتمعات) ، تفتقر اللغة إلى شيء مفيد.

بدافع الاهتمام ، عندما جلس فريق TypeScript حول طاولة وناقش فئات abstract ، هل رفع أي شخص يده وقال "ولكن ماذا عن final

RyanCavanaugh همهمة أنا أفهم نقاطك

أعتقد أنه كان في الغالب سوء فهم (أعتقد من الطريقة التي أوضحنا بها)

@ series0ne ملخص جيدًا حقًا أن نوايانا لم تكن معقدة للغاية في الإخراج المطبوع من خلال طلب إنشاء فئة نهائية في JS (حسنًا ، سيكون هذا بمثابة حطام قطار للقيام بذلك) ولكن فقط لإنشاء قواعد إضافية لإخبار الناس: لا يمكنك ذلك. ر تفعل ذلك. ويخبر مستخدم واجهة برمجة التطبيقات أنه ربما لا ينبغي له العبث بهذه الفئة (من أجل الاستقرار ، وسبب الأمان ، إلخ) كل شيء في الملفات المطبوعة / المترجم ليس على الإخراج.

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

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

أرى أن الكلمة الأساسية النهائية / المختومة يمكن أن تعقد الكثير من الجوانب خاصة: إصلاح الأخطاء ، التصحيح ، تغيير السلوك.

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

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

بعد هذا ، على الرغم من أنني قد أسيء فهم نفسي للمواقف الآن ، لذا كن حراً في شرح ذلك لي :)

آه إذا كنت أتذكر أنني كنت أقرأ الكثير عن ES4 (لست متأكدًا من أنني كنت لا أزال طفلاً عندما كانت المسودة في إنتاجات لول) ومن المدهش أنها تبدو مشابهة حقًا لـ Typescript.

ويقال في مسودة المواصفات هنا:
https://www.ecma-international.org/activities/Languages/Language٪20overview.pdf

A class that does not explicitly extend any other class is said to extend the class Object. As a consequence, all the classes that exist form an inheritance hierarchy that is a tree, the root of which is Object. A class designated as final cannot be extended, and final methods cannot be overridden: class C { final function f(n) { return n*2 } } final class D extends C { function g() { return 37 } }

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

لدي حالة استخدام واحدة بالكاد واجهتني ودفعتني لإيجاد هذه المشكلة. تدور حول استخدام this كنوع إرجاع:

abstract class TileEntity {
    //constructor, other methods...
    abstract cloneAt(x: number, y: number): this;
}

كانت نيتي في كتابة هذا هو التأكد من أن TileEntities غير قابلة للتغيير (وبالتالي آمنة للتنقل) ولكن يمكن استنساخ أي TileEntity مع بعض الخصائص المتغيرة (في هذه الحالة x و y ) دون الحاجة إلى معرفة أي شيء عن شكل الفئة الفرعية. هذا ما أريد كتابته ، لكن محاولة كتابة تنفيذ (بشكل صحيح) يؤدي إلى تعطل هذا.

class TurretTileEntity extends TileEntity {
    //constructor, other methods...
    cloneAt(x: number, y: number): this {
        return new TurretTileEntity(x, y, /* ... other properties */);
    }
}

تكمن المشكلة في أنه بدون القدرة على التصريح بأنه لن يكون هناك أبدًا فئة فرعية من TurretTileEntity ، لا يمكن تضييق نوع الإرجاع this ليقتصر على النوع TurretTileEntity فقط.

تأثير هذا النقص في Typescript ضئيل ، مع الأخذ في الاعتبار أنه يمكنك تحويل قيمة الإرجاع إلى <any> . هذا ، بشكل موضوعي ، مضاد ، ومؤشر مفيد على أن نظام الكتابة يمكن أن يكون أكثر تعبيرًا. يجب دعم الفصول النهائية / المختومة.

بدافع الاهتمام ، عندما جلس فريق TypeScript حول طاولة وناقشوا الفصول المجردة ، هل رفع أي شخص يده وقال "ولكن ماذا عن النهائي"؟

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

أعتقد أن الفصول والأساليب النهائية مهمة للغاية. أتمنى أن تنفذها.

لاحظ أن هذه المشكلة تتعلق بالفصول النهائية / المختومة. كانت هناك مناقشة خارج الموضوع للطرق النهائية / المختومة والتي تعتبر مفهومًا مختلفًا تمامًا.

أغلق mhegazy https://github.com/Microsoft/TypeScript/issues/9264 لصالح هذه المشكلة. هل هناك مشكلة منفصلة لم يتم إغلاقها كمخادع لتتبع الطرق النهائية / المختومة؟

crcla من قراءة بعض تعليقات RyanCavanaugh أعلاه ، أعتقد أن الأساس المنطقي لإغلاق القضية الأخرى هو أن دعم الفصول النهائية / المختومة يشمل أساليب دعم نهائية / مختومة. كلا الموضوعين وثيق الصلة بالموضوع.

لا أستطيع أن أصدق أن اقتراح final يحمل عنوان Won't fix .

قم بتغيير التسمية مرة أخرى إلى In Discussion وقم بتطبيقها ، من فضلك!

في حالتي ، أريد كتابة فئة أساسية مجردة للمكونات الإضافية وأريد التأكد من أن فئة المكون الإضافي لا يمكنها الكتابة فوق طرق الفئة الأساسية الخاصة بي عن طريق الخطأ. لا يمكن لأي من private constructor ، Object.seal القيام بهذه المهمة.

لأولئك الذين يرون أن هذا ميزة حاسمة ، العيش أو الموت: إنها في الحقيقة ليست كذلك. إذا كانت واجهة برمجة التطبيقات (API) الخاصة بك تتكون من الكشف عن تطبيق فئة يحتاج إلى تمديد من قبل المستهلك ، فهناك طرق أفضل للقيام بذلك. لا تتبع مثال React السيئ. فقط استخدم الوظائف والأشياء البسيطة ، واترك هذا الهراء في مكانه: في الماضي.

الآن قم بإحضار التصويتات السلبية 😀

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

pelotom إذا كنت لا ترغب في استخدام يخبرك أن تفعل خلاف ذلك ، ولكن يجب أن ينطبق الشيء نفسه في الاتجاه المعاكس: إذا أراد شخص ما استخدام
من خلال إجبار الآخرين على تبني نمط معين (غير OOP) ، فأنت تتبنى نفس السلوك الذي تستنكره OOP من أجله. على الأقل كن متسقًا :)

لا تعد إضافة كلمة رئيسية final إلى TypeScript تغييرًا جذريًا ولن تؤثر على أي من مشاريعك الحالية بأي شكل من الأشكال ، ولكنها ستكون ميزة حيوية لأشخاص مثل thorek وأنا والعديد من الأشخاص الآخرين.

إذا أراد شخص ما استخدام بنيات OOP ، فما عليك سوى السماح لهم بذلك.

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

fwiw ، من المحتمل أن نشجع عملائنا (google) على استخدام final في التعليقات حتى ينتشر إلى مجمع الإغلاق: \

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

dimiVergos هذه هي حالتي بالضبط ، وأفترض نفس الشيء بالنسبة للعديد من الآخرين. أستطيع أن أتخيل أنني قد أبدو متحيزًا بسبب موقفي ، ولكن يبدو أنه الاستخدام الوحيد المبرر (وإن كان بدرجة عالية) لهذه الكلمة الرئيسية وفقًا لتجربتي.

أنا منفتح على التصحيحات على هذا!

أهتم أكثر بدعم الطرق النهائية (لتجنب تجاوز الفئات الفرعية عن طريق الخطأ) أكثر مما أهتم به في الفصول النهائية. هل البطاقة الصحيحة للتصويت لذلك؟ يبدو أن التذكرة https://github.com/Microsoft/TypeScript/issues/9264 تدل على ذلك.

فكيف أصوت لـ "الطرق النهائية"؟ أم أنني فقط قمت بالتصويت له من خلال هذا التعليق؟ أيضا كيف نضيف "طرق" إلى العنوان؟ هل يمكنني تعديله فقط؟ يقتصر العنوان الحالي بشكل مضلل على الفصول فقط ، لكن المناقشة تتضمن أيضًا طرقًا.

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

class parent {
  public get finalMethod(): () => void {
    return () => {
      // final logic
    };
  }
}

class child extends parent {
  // ERROR "Class 'parent' defines instance member accessor 'finalMethod', but extended class 'child' defines it as instance member function"
  public finalMethod(): void { }
}

إليك حالة استخدام أخرى في العالم الحقيقي لطرق final . ضع في اعتبارك الامتداد التالي لـ React.Component لتسهيل تنفيذ سياق بسيط.

interface FooStore{
  foo: string;
}

const {Provider, Consumer} = React.createContext<FooStore>({
  foo: 'bar';
});

abstract class FooConsumerComponent<P, S> extends React.Component<P, S> {

  // implement this instead of render
  public abstract renderWithStore(store: FooStore): JSX.Element;

  public final render() {
    return (
      <Consumer>
        {
          (store) => {
            return this.renderWithStore(store);
          }
        }
      </Consumer>
    );
  }
}

بدون final على طريقة render() ، لا شيء يمنع المرء من تجاوز الطريقة بشكل غير صحيح ، وبالتالي كسر كل شيء.

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

الحل الوحيد الذي وجدته هو استخدام أسلوب الديكور مثل:
function sealed(target, key,descriptor){ descriptor.writable = false; // Prevent method to be overriden }

ثم في صنفك "الأساسي" ، استخدم الزخرفة لمنع تجاوز الطريقة ، على سبيل المثال:

class MyBaseClass {
<strong i="10">@sealed</strong>
public MySealedMethod(){}

public OtherMethod(){}

...
}

بهذه الطريقة لا يمكن (بسهولة) تجاوز "MySealedMethod" في الصف الفرعي. مثال:

class AnotherClass extends MyBaseClass {
public MySealedMethod(){} ====>> ERROR at RUNTIME (not at compile time)
}

في الواقع ، الجانب السلبي الوحيد لهذا الحل هو أن "مختوم" يكون مرئيًا فقط في وقت التشغيل (خطأ في وحدة تحكم جافا سكريبت) ولكن ليس في وقت الترجمة (حيث يتم تعيين خصائص الطريقة عبر الوظيفة التي أعتقد)

تضمين التغريدة

نعم فعلا. في كل مرة نضيف فيها كلمة رئيسية ، "ولكن بعد ذلك سيتعين علينا إضافة هذه الكلمة الرئيسية الأخرى أيضًا!" هي نقطة قوية ضد إضافتها ، لأننا نريد تنمية اللغة بأكبر قدر ممكن من الدقة.

يبدو لي أنك تبدأ هذه الحجة مع وضع عقلك في مواجهة هذه الميزة. لا ينبغي أن تكون السمة الشائعة نقطة ضد النظر في هذه الميزة. يجب أن يكون هدفك أن تسأل نفسك - لماذا هي شعبية - ثم تفكر مليًا في الأمر.

أنا متأكد من أنك ناقشتها وتم تداول الحجج حول التفكير فيها أو ضدها. هل الحجة ضدها مجرد زحف للميزات ، أم أن هناك أي شيء أكثر تحديدًا؟ هل تعتبرها ميزة هامشية؟ إذا كان الأمر كذلك ، فهل يمكننا فعل شيء لتغيير رأيك؟

اسمحوا لي فقط أن أترك هذه الأسئلة هنا لكي نفكر فيها جميعًا.

هل هناك طريقة لإغلاق الفصل _ بالتصميم_ باستخدام التركيبات الحالية؟
إذا تمت إضافة الميزة ، فهل ستسمح لنا بعمل أي شيء جديد؟ (كما هو الحال في شيء ما لا تسمح به التركيبات الحالية)
إذا كانت الميزة تسمح لنا بعمل شيء جديد ، فهل هو شيء ذو قيمة؟
هل ستؤدي إضافة فصول مختومة إلى زيادة تعقيد اللغة أكثر من اللازم؟
هل ستؤدي إضافة فئات مختومة إلى زيادة تعقيد المترجم كثيرًا؟

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

لمعلوماتك: سأكون رائعًا إذا كانت مواجهة هذه الميزة أكثر قليلاً من مجرد عبارات شاملة ضد زحف الميزة.

asimonf أعتقد أن كل ما قلته قد تمت معالجته بالفعل بواسطة هذا التعليق (ستحتاج إلى توسيع قسم "إظهار المزيد" لرؤيته) والقسم الذي يليه.

ما الذي قد يغير رأينا هنا؟ يظهر الأشخاص بأمثلة من التعليمات البرمجية التي لم تعمل بالطريقة التي يجب أن تعمل بها لأن الكلمة الرئيسية sealed كانت مفقودة .

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

لماذا يجب أن تحتوي TypeScript على هذه الكلمة الأساسية عندما يكون الموقف بالفعل واحدًا كان يجب أن تكون قد واجهت فيه على الأقل حاجزين منفصلين يخبرك بعدم التواجد هناك لتبدأ؟

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

الحالة الحقيقية التي سأستخدمها النهائية هي منع تجاوز طريقة بشيء لا يسمي أبدًا الطريقة الفائقة. بعض الطرق العامة بالطبع. لكن الحل الحقيقي الذي توصلت إليه هو القدرة على إجبار أي طريقة فرعية على استدعاء الطريقة الفائقة. https://github.com/Microsoft/TypeScript/issues/21388

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

أعتقد أنه يوجد أعلاه الكثير من الأمثلة الممتازة حول متى / حيث لن يكون final مفيدًا فحسب ، بل يوفر _قيمة حقيقية _ و _ أمانًا حقيقيًا_ للمنصة التي يتم بناؤها. لا يختلف الأمر بالنسبة لي. كما قلت ، لا أعرف الكثير عن تعقيدات تصميم اللغة ، لكن من الواضح أن هذه ميزة يريدها الناس / سيستخدمونها / لا أستطيع حقًا أن أرى طريقة لإساءة استخدامها أو أنها ستولد رمزًا سيئًا. أفهم مفهوم الخوف من زحف النطاق ولكن مطوري TS ليسوا مضطرين إلى تنفيذ كل ما يريده المجتمع.

فقط لإضافة جزء مني إلى المناقشة ، أود أن أضع إبهامي على جانب "نعم" من المقياس لأن هذه القضية مليئة بالحجج الجيدة التي تدعم إضافة الميزة ، ومع ذلك فإن الحجج ضد ذلك التي أراها هي:

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

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

أتمنى أن يكون هذا بناء! أحب TS وأريد أن أراها تتحسن!

👍

--تعديل--

ردًا على RyanCavanaugh :

So what problem is being solved?

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

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

تركزت معظم المناقشات الأخيرة على الأساليب النهائية (أقل من ذلك على الفصول النهائية). الأساليب النهائية هي بالتأكيد اهتمامي الأساسي. لقد لاحظت للتو أنه إذا قمت بتوسيع رابط "هذا التعليق" في مشاركة RyanCavanaugh السابقة ، فإنه يعتبر مناقشة الطريقة النهائية خارج الموضوع. ومع ذلك ، اقترح mhegazy أن هذه التذكرة هي المكان المناسب (عند إغلاق # 9264). لذا ، بصفتي مستخدمًا نهائيًا متواضعًا ، أشعر بالحيرة تجاه المكان الذي يجب أن أطلب منه / التصويت للطرق النهائية. سيكون موضع تقدير التوجيه.

تضمين التغريدة
التناقض هو شيء لاحظته أيضًا ولكن لم أشر إليه في رسالتي خوفًا من الصراخ (لقد وجدت بالفعل هذا الموضوع من خلال # 9264 وجئت إلى هنا في اتجاه mhegazy ).
تضمين التغريدة
تضمين التغريدة
وفقًا للتعليق أعلاه ، حيث _ هو المكان الصحيح لمناقشة الطرق النهائية ، لأن هذا في الواقع هو الشيء الذي أهتم به كثيرًا.

إذا نظرنا إلى الوراء على تعليقي الذي حصل على تصويت سلبي بشدة (تأكد من إضافة 👎 الخاص بك إذا لم تكن قد فعلت ذلك بعد!) يسعدني الإبلاغ عن أن React _ لم يعد _ يعد مثالًا سيئًا عن طريق فرض واجهة برمجة تطبيقات تستند إلى class -based على مستخدميها! مع اقتراح هوكس ، استعاد فريق React رشدهم وتبنى نهجًا وظيفيًا أبسط جذريًا. مع ذلك ، تبخر السبب الأخير الذي دفع العديد من المطورين إلى استخدام الفئات على الإطلاق ، وبئس المصير. سأكرر: كل ما تعتقد أنك بحاجة إليه يمكن أن يتم بشكل أفضل بدونها .

مستقبل JS و TS بلا طبقات ، الحمد لله!

cbutterfield لقد لاحظت ذلك أيضًا ، وإذا تم إغلاق المشكلة رقم 9264 لمناقشتها في هذه المشكلة ، أعتقد أن العنوان يجب أن يتغير إلى Suggestion: Final keyword for classes and methods ، وإلا فقد لا يضيف الأشخاص الذين يبحثون عن طرق نهائية (حصريًا) رد فعل في أول وظيفة.

نقلا عن mhegazy :
تستخدم Java و / أو C # فئة final لتحسين فصلك في وقت التشغيل ، مع العلم أنها لن تكون متخصصة. أود أن أزعم أن هذا هو القيمة الرئيسية للدعم النهائي. في TypeScript ، لا يوجد شيء يمكننا تقديمه لجعل الكود الخاص بك يعمل بشكل أفضل مما كان عليه بدون نهائي.

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

نعم ، يمكن حل هذه المشكلات عن طريق إضافة تعليقات أو واجهات ، ولكن final هو حل أنيق لتقليل واجهة برمجة التطبيقات المرئية إلى الوظائف الضرورية عندما يكون كل ما تريده هو فئة بسيطة بواجهة برمجة تطبيقات نظيفة قابلة للتمديد.

على الرغم من أن هذه المشكلة عمرها 3 سنوات تقريبًا ، يجب أن يكون لدينا بالفعل كلمة رئيسية final حيث توجد بالفعل كلمة رئيسية abstract .

ضع في اعتبارك أننا لا نريد إجبار الناس على استخدامه وهي ميزة مفيدة مثل الكلمة الأساسية المجردة. ولكن إليك حالة استخدام أخرى ستُظهر بقوة فائدة الكلمة الرئيسية final :

abstract class A {
  protected abstract myVar: string;

  protected abstract myFunction(): void;
}

class B extends A {
  protected readonly myVar: string = "toto";

  constructor() {
    super();
    this.myFunction();
  }

  protected myFunction() {
    console.log(this.myVar);
  }
}

class C extends B {
  constructor() {
    super();
  }

  protected myFunction() {
    console.log("tata");
  };

  public callFunction = () => {
    this.myFunction();
  }
}

const myB = new B(); // toto

const myC = new C(); // toto
myC.callFunction(); // tata

النتيجة بعد التجميع:

toto
tata

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

إذن ماذا لو ذهبنا إلى أبعد من ذلك في عملية التحويل البرمجي Typescript واستخدمنا readonly لحماية سماتنا (وتظاهرنا بأن أساليبنا خصائص)؟

class B extends A {
  [...]

  protected readonly myFunction = () => {
    console.log(this.myVar);
  }
}

class C extends B {
  protected myVar: string = "I am not protected that much";
  [...]

  protected myFunction = () => { // using the readonly keyword doesn't prevent any modification
    console.log("tata"); // If you launch this code, tata will still be logged in the console.
  };
}

(لاحظ أن الكود يتم تجميعه باستخدام tsc ، ولا توجد أخطاء عند تجميعه أو تنفيذه)
إذن لدينا الآن مشكلتان:

  • نحن لا نحمي سماتنا B ، لذلك نحن بحاجة إلى طريقة لمنع أي وراثة غير متوقعة.
  • نحن نعلم الآن أنه يمكننا تجاوز أي خصائص readonly خلال تمديد فئتها ، و YES ، يعرف Typescript أنها الخاصية الرئيسية التي نقوم بتغييرها باستخدام private بدلاً من protected في فئة C سيظهر خطأ لأنه ليس من نفس نوع الوصول / الرؤية.

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

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

TL. dr: الكلمة الأساسية final ستحل مشكلتين (على الرغم من أن التحقق من readonly سيكون بداية جيدة لمنع أي إعادة كتابة غير مصرح بها)

بعد ثلاث سنوات ... إنه أمر سخيف للغاية.

لإثبات الحاجة إلى هذه الميزة ، أقترح إلقاء نظرة على ما تم إنجازه بلغات أخرى:

Java:
final class SomeClass { ... }
PHP:
final class SomeClass { ... }
C#:
sealed class SomeClass {...}
C++:
class SomeClass final { ... }
Delphi:
type SomeClass = class sealed() ... end;

لذلك ، نرى أنه في جميع لغات OOP الأكثر شيوعًا ، توجد هذه الميزة لأنها تأتي من منطق الوراثة لـ OOP.

كما يجب أن أقتبس قول قائد ديف لـ TS

إذا كان لدينا فئات نهائية ، فسنحتاج أيضًا إلى طرق أو خصائص نهائية.

لست متأكدًا مما إذا كان الأمر مثيرًا للسخرية ، ولكن في JS ، يتم استخدام الكلمة الأساسية للقراءة فقط للخصائص (والأساليب إذا كنت تغش) ، لذا فهذه نقطة غبية جدًا.

وربما يكون عدم السماح لشخص ما بإغلاق القضية عندما يكون لديه +40 تصويتًا معارضًا ، مما يعني أن المجتمع يختلف معه بشدة ، سيكون نصيحة جيدة لتجنب المزيد من المواقف الغبية.

إذا لم تكن مهتمًا بتعزيز الميزة الرئيسية لـ Typescript ، فالرجاء قولها بصوت عالٍ حتى تتمكن أخبار التكنولوجيا من نقل ذلك على Twitter ، لأنه بخلاف ذلك ، إنها مجرد ضجة سيئة مخفية. أنت تتجاهل مجتمعك فقط ، وليس لديك أي عملية لجعل المجتمع يتحقق مما نحتاجه أم لا.

ربما عدم السماح لشخص واحد بإغلاق القضية عندما يكون لديه +40 تصويتًا معارضًا مما يعني أن المجتمع يختلف معه بشدة سيكون نصيحة جيدة لتجنب المزيد من المواقف الغبية

أنا لست "رجل واحد". عندما أتخذ قرارات هنا ، فإن ذلك يكون انعكاسًا لعملية صنع القرار لفريق TypeScript بأكمله. نظر فريق التصميم في هذه المشكلة عدة مرات ، وفي كل مرة توصلوا إلى نفس النتيجة. أنت مدعو إلى عدم الموافقة على هذه النتيجة ، لكن العملية ليست قابلة للنقاش.

ليس لديك أي عملية لجعل المجتمع يتحقق مما نحتاجه أم لا.

هذه هي العملية هنا: أنت تصف تلخيصي لمنطقنا بأنه "غبي" وأنا (والأشخاص الآخرون في الفريق) أقرأه. نحن نستمع إلى ردود الفعل.

أعلم أن الإشارة إلى الميزات المنفذة الأخرى كأسباب للنظر في هذه الميزة هي رائحة وليست حجة حقًا ، لكنني أجد أنه من المفارقات أنه تم النظر في آلية التعرّف على النوع وإضافتها (قد يكون رائعًا ، ولكن يمكن للمرء بالتأكيد العيش بدونها ) لكن شيئًا كهذا مرفوض.

في النهاية ، يمكنني العيش بدون مثل هذه الميزة ، ولكن يمكن قول الشيء نفسه عن نصف ميزات TS. إذن ، ما هو السبب المناسب للنظر في تنفيذ هذا؟

يخفي GitHub الكثير من التعليقات هنا بشكل غير مفيد ، لذلك أعيد نشر الردود المختلفة (بالإضافة إلى بعض الإضافات) التي قدمناها في الماضي. إضافة بعض الأفكار أدناه أيضًا.


تم النظر في بعض النقاط عندما استعرضنا هذه المرة الأخيرة

  • الفئات هي ميزة JAVASCRIPT ، وليست ميزة مميزة . إذا كنت تشعر حقًا أن الفصول الدراسية عديمة الفائدة تمامًا بدون final ، فهذا شيء يجب تناوله مع لجنة TC39 أو طرحه للمناقشة. إذا لم يكن هناك من يرغب أو قادر على إقناع TC39 بأن final ميزة لا غنى عنها ، فيمكننا التفكير في إضافتها إلى TypeScript.
  • إذا كان من القانوني استدعاء new على شيء ما ، فإن ذلك يحتوي على مراسلات وقت تشغيل واحد لواحد مع وراثة منه. فكرة الشيء الذي يمكن أن يكون new 'd وليس super ' d فقط غير موجودة في JavaScript
  • نحن نبذل قصارى جهدنا لتجنب تحويل TypeScript إلى حساء الكلمات الرئيسية OOP. هناك العديد من آليات التكوين الأفضل من الميراث في JavaScript ولا نحتاج إلى امتلاك كل كلمة رئيسية واحدة في C # و Java.
  • يمكنك كتابة فحص وقت التشغيل بشكل تافه لاكتشاف الميراث من فصل دراسي "يجب أن يكون نهائيًا" ، وهو ما يجب عليك فعله على أي حال إذا كنت "قلقًا" بشأن شخص يرث عن غير قصد فصلك الدراسي نظرًا لأن جميع المستهلكين قد لا يستخدمون TypeScript .
  • يمكنك كتابة قاعدة نسالة لفرض اصطلاح أسلوبي لم يتم توريث فئات معينة منه
  • السيناريو الذي يرثه شخص ما "عن طريق الخطأ" من الفصل الذي يجب أن يكون مختومًا هو نوع من السيناريو الفردي. أود أن أزعم أيضًا أن التقييم الفردي لشخص ما لما إذا كان من الممكن أن يرث من فئة معينة أم لا هو على الأرجح مشكوك فيه.
  • هناك ثلاثة أسباب أساسية لإغلاق فصل دراسي: الأمان والأداء والنية. اثنان من هؤلاء لا معنى له في TypeScript ، لذلك علينا أن نأخذ في الاعتبار التعقيد مقابل الكسب لشيء يقوم فقط بثلث المهمة التي يقوم بها في أوقات التشغيل الأخرى.

لم أسمع حجة مقنعة لماذا لا تحتاجها TS

مجرد تذكير بأن هذه ليست الطريقة التي يعمل بها. تبدأ جميع الميزات من -100 . من هذا المنصب

في بعض هذه الأسئلة ، تتساءل الأسئلة عن سبب "استبعادنا" أو "استبعادنا" لميزة معينة. تشير هذه الصياغة إلى أننا بدأنا بلغة حالية (C ++ و Java هي الخيارات الشائعة هنا) ، ثم بدأنا في إزالة الميزات حتى وصلنا إلى النقطة التي أحببناها. وعلى الرغم من أنه قد يكون من الصعب على البعض تصديق ذلك ، فهذه ليست الطريقة التي تم تصميم اللغة بها.

لدينا ميزانية معقدة محدودة. كل ما نقوم به يجعل كل ما نقوم به أبطأ بنسبة 0.1٪. عندما تطلب ميزة ، فأنت تطلب أن تصبح كل ميزة أخرى أصعب قليلاً ، وأبطأ قليلاً ، وأقل احتمالاً قليلاً. لا شيء يدخل إلى الباب هنا لأنه يحتوي على Java أو لأنه يحتوي على C # أو لأنه سيكون فقط بضعة أسطر من التعليمات البرمجية أو يمكنك إضافة مفتاح سطر أوامر . تحتاج الميزات إلى دفع تكاليفها وتكاليف عبئها الكامل على المستقبل.


ما الذي قد يغير رأينا هنا؟ يظهر الأشخاص بأمثلة من التعليمات البرمجية التي لم تعمل بالطريقة التي يجب أن تعمل بها لأن الكلمة الرئيسية final كانت مفقودة .

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

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

لماذا يجب أن تحتوي TypeScript على هذه الكلمة الأساسية عندما يكون الموقف بالفعل واحدًا كان يجب أن تكون قد واجهت فيه على الأقل حاجزين منفصلين يخبرك بعدم التواجد هناك لتبدأ؟

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

إذا لم تكن مهتمًا بتعزيز الميزة الرئيسية لـ Typescript ، فيرجى قولها بصوت عالٍ حتى تتمكن الأخبار التقنية من نقل ذلك على Twitter

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


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

يمكنك بسهولة تخيل بعض الكلمات الأساسية التي تم تطبيقها على طريقة وفرضت تلك الطرق المشتقة التي يطلق عليها عبر super . إذا كانت C # و Java تحتويان على هذه الكلمة الرئيسية ، فسيقوم الأشخاص بتطبيق هذه الكلمة الرئيسية تمامًا في الأماكن التي يكون فيها ذلك منطقيًا. في الواقع ، يمكن القول إنه يتم فرضه بشكل أكثر شيوعًا من final ، لأنه من المستحيل تطبيق فحص وقت التشغيل ، وهو جانب أكثر دقة من العقد المشتق من الأساس من "الفئات المشتقة قد لا تكون موجودة ". سيكون مفيدًا في مجموعة متنوعة من الطرق التي لن يكون بها final . أفضل استخدام هذه الكلمة الرئيسية بدلاً من هذه (على الرغم من أنني أعتقد أنه لا يتوافق مع التعقيد مقابل شريط القيمة).

إذن ، ما هو السبب المناسب للنظر في تنفيذ هذا؟

عندما ننظر إلى التعليقات ، تبدو الاعتبارات القوية كما يلي:

  • لا يمكنني التعبير بشكل كافٍ عن سلوك مكتبة JavaScript هذه
  • تم تجميع الكود الخاص بي ، ولكن في الحقيقة لا ينبغي أن يكون لأنه يحتوي على هذا الخطأ (الدقيق)
  • لم يتم توصيل القصد من هذا الرمز بشكل كافٍ بواسطة نظام النوع

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

لم نر أبدًا تعليقات مثل "لقد أمضيت ساعات في تصحيح الأخطاء لأنني كنت أحاول أن أرث من فصل لم يكن في الواقع من فئة فرعية" - قال أحدهم إن ذلك سيؤدي بحق إلى "وات" لأنه لا يمكن تخيله حقًا. حتى لو كان المُعدِّل موجودًا ، فلن يساعد هذا الموقف حقًا ، لأن المكتبات لا توثق ما إذا كان من المفترض أن تكون الفصول نهائية - على سبيل المثال ، هل fs.FSwatcher final ؟ يبدو أنه حتى مؤلفو العقدة لا يعرفون. لذا فإن final كافٍ إذا علم المؤلفون أنه final ، لكن سيتم توثيق ذلك بغض النظر ، ونقص final لا يخبرك حقًا بأي شيء لأنه غالبًا ببساطة غير معروف في كلتا الحالتين.

قرأت المجموعة بالكامل وفهمت بيان الفريق بشأن اختيار الميزات ، وسأعود فقط إلى نقاط معينة من تعليقاتي

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

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

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

لا أعتقد أن final هو الخطوة الأولى لأن هناك بالفعل اقتراحًا للكلمة الرئيسية private https://github.com/tc39/proposal-private-methods

أنا متشكك بشأن You should a comment to say *dont do this* ، إنه أشبه بالقول في نموذج Hey don't write down specific characters ، لقد قمت بالشفرة منذ سنوات تقريبًا ، لذا يجب أن تعرف القاعدة رقم 1 للمطور: لا تثق أبدًا في المستخدم ( والمطور الذي سيستخدم الكود الخاص بك)

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

ونظرًا لأن جافا سكريبت مقيد بذلك ، فقد اعتقد المجتمع أن Typescript يمكن أن تتجاوز هذا الحد ، ولهذا السبب استمرت هذه المشكلة لمدة 3 سنوات ، ولهذا السبب لا يزال الناس يتساءلون عن سبب عدم وجود هذه الميزة ، ولهذا السبب نريد من المترجم أن قم بإجراء الفحص اليدوي للفصل و / أو الطريقة.

لم تنتظر JS للحصول على طرق خاصة / عامة لتنفيذها ، على الرغم من وجود مقترحات فعلية لتضمينها مع الكلمة الرئيسية # (مطول أقل من public / private ) ، أعلم أنك أردت إنشاء لغة مثالية لأن الكمال ليس عندما لا يمكنك إضافة أي شيء بعد الآن ، إنه عندما لا يمكنك إزالة أي شيء بعد الآن.

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

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

شكرا على الرد بالمناسبة ، لا كراهية أو سلوك سيء موجه ضد فريق التطوير أو ضدك.

جميع النقاط الصالحة! ولكن ، من فضلك دعنا نقسم المناقشة بين

أ) دعم الفصول النهائية
ب) دعم الأساليب النهائية

في حين أن جميع الحجج الخاصة بك تستهدف أ) - لا شيء أهداف ب.

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

Am 28.01.2019 أم 20:32 schrieb Ryan Cavanaugh [email protected] :

يخفي GitHub الكثير من التعليقات هنا بشكل غير مفيد ، لذلك أعيد نشر الردود المختلفة (بالإضافة إلى بعض الإضافات) التي قدمناها في الماضي. إضافة بعض الأفكار أدناه أيضًا.

تم النظر في بعض النقاط عندما استعرضنا هذه المرة الأخيرة

الفئات هي ميزة JAVASCRIPT ، وليست ميزة مميزة. إذا كنت تشعر حقًا أن الفصول الدراسية غير مجدية تمامًا بدون نهائية ، فهذا شيء يجب تناوله مع لجنة TC39 أو طرحه للمناقشة. إذا لم يكن هناك من يرغب أو قادر على إقناع TC39 بأن الميزة النهائية هي ميزة لا غنى عنها ، فيمكننا التفكير في إضافتها إلى TypeScript.
إذا كان من القانوني استدعاء شيء جديد على شيء ما ، فإن ذلك يحتوي على مراسلات وقت تشغيل واحد لواحد مع الوراثة منه. فكرة الشيء الذي يمكن أن يكون جديدًا ولكن ليس ممتازًا لا توجد في جافا سكريبت
نحن نبذل قصارى جهدنا لتجنب تحويل TypeScript إلى حساء الكلمات الرئيسية OOP. هناك العديد من آليات التكوين الأفضل من الميراث في JavaScript ولا نحتاج إلى امتلاك كل كلمة رئيسية واحدة في C # و Java.
يمكنك كتابة فحص وقت التشغيل بشكل تافه لاكتشاف الميراث من فصل دراسي "يجب أن يكون نهائيًا" ، وهو ما يجب عليك فعله على أي حال إذا كنت "قلقًا" بشأن شخص يرث عن غير قصد فصلك الدراسي نظرًا لأن جميع المستهلكين قد لا يستخدمون TypeScript .
يمكنك كتابة قاعدة نسالة لفرض اصطلاح أسلوبي لم يتم توريث فئات معينة منه
السيناريو الذي يرثه شخص ما "عن طريق الخطأ" من الفصل الذي يجب أن يكون مختومًا هو نوع من السيناريو الفردي. أود أن أزعم أيضًا أن التقييم الفردي لشخص ما لما إذا كان من الممكن أن يرث من فئة معينة أم لا هو على الأرجح مشكوك فيه.
هناك ثلاثة أسباب أساسية لإغلاق فصل دراسي: الأمان والأداء والنية. اثنان من هؤلاء لا معنى له في TypeScript ، لذلك علينا أن نأخذ في الاعتبار التعقيد مقابل الكسب لشيء يقوم فقط بثلث المهمة التي يقوم بها في أوقات التشغيل الأخرى.
لم أسمع حجة مقنعة لماذا لا تحتاجها TS

مجرد تذكير بأن هذه ليست الطريقة التي يعمل بها. تبدأ جميع الميزات من -100 https://blogs.msdn.microsoft.com/ericgu/2004/01/12/minus-100-points/ . من هذا المنصب

في بعض هذه الأسئلة ، تتساءل الأسئلة عن سبب "استبعادنا" أو "استبعادنا" لميزة معينة. تشير هذه الصياغة إلى أننا بدأنا بلغة حالية (C ++ و Java هي الخيارات الشائعة هنا) ، ثم بدأنا في إزالة الميزات حتى وصلنا إلى النقطة التي أحببناها. وعلى الرغم من أنه قد يكون من الصعب على البعض تصديق ذلك ، فهذه ليست الطريقة التي تم تصميم اللغة بها.

لدينا ميزانية معقدة محدودة. كل ما نقوم به يجعل كل ما نقوم به أبطأ بنسبة 0.1٪. عندما تطلب ميزة ، فأنت تطلب أن تصبح كل ميزة أخرى أصعب قليلاً ، وأبطأ قليلاً ، وأقل احتمالاً قليلاً. لا شيء يدخل هنا لأن Java تمتلكها أو لأن C # بها أو لأنها ستكون مجرد بضعة أسطر من التعليمات البرمجية أو يمكنك إضافة مفتاح سطر أوامر. تحتاج الميزات إلى دفع تكاليفها وتكاليف عبئها الكامل على المستقبل.

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

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

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

لماذا يجب أن تحتوي TypeScript على هذه الكلمة الأساسية عندما يكون الموقف بالفعل واحدًا كان يجب أن تكون قد واجهت فيه على الأقل حاجزين منفصلين يخبرك بعدم التواجد هناك لتبدأ؟

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

إذا لم تكن مهتمًا بتعزيز الميزة الرئيسية لـ Typescript ، فيرجى قولها بصوت عالٍ حتى تتمكن الأخبار التقنية من نقل ذلك على Twitter

نحن صريحون جدًا بشأن كيفية تصميم اللغة https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals ؛ غير الهدف رقم واحد يتحدث بالضبط عن هذا الاقتراح.

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

يمكنك بسهولة تخيل بعض الكلمات الرئيسية التي تم تطبيقها على طريقة وفرضت تلك الطرق المشتقة التي يطلق عليها عبر https://github.com/Microsoft/TypeScript/issues/21388 . إذا كانت C # و Java تحتويان على هذه الكلمة الرئيسية ، فسيقوم الأشخاص بتطبيق هذه الكلمة الرئيسية تمامًا في الأماكن التي يكون فيها ذلك منطقيًا. في الواقع ، يمكن القول إن تطبيقه أكثر شيوعًا من تطبيقه نهائيًا ، لأنه من المستحيل تطبيق فحص وقت التشغيل ، وهو جانب أكثر دقة من العقد المشتق من الأساس من "الفئات المشتقة قد لا تكون موجودة". سيكون مفيدًا بعدة طرق لن تكون نهائية. أفضل استخدام هذه الكلمة الرئيسية بدلاً من هذه (على الرغم من أنني أعتقد أنه لا يتوافق مع التعقيد مقابل شريط القيمة).

إذن ، ما هو السبب المناسب للنظر في تنفيذ هذا؟

عندما ننظر إلى التعليقات ، تبدو الاعتبارات القوية كما يلي:

لا يمكنني التعبير بشكل كافٍ عن سلوك مكتبة JavaScript هذه
تم تجميع الكود الخاص بي ، ولكن في الحقيقة لا ينبغي أن يكون لأنه يحتوي على هذا الخطأ (الدقيق)
لم يتم توصيل القصد من هذا الرمز بشكل كافٍ بواسطة نظام النوع
النتائج النهائية لهذه ، ولكن أيضًا المُعدِّل الذي يقول "لا يمكن استدعاء هذه الوظيفة مرتين متتاليتين" أو "لا ينتهي إنشاء هذه الفئة حقًا حتى علامة التجزئة غير المتزامنة التالية". لا يجب أن يوجد كل شيء يمكن تخيله.

لم نر أبدًا تعليقات مثل "لقد أمضيت ساعات في تصحيح الأخطاء لأنني كنت أحاول أن أرث من فصل لم يكن في الواقع من فئة فرعية" - قال أحدهم إن ذلك سيؤدي بحق إلى "وات" لأنه لا يمكن تخيله حقًا. حتى إذا كان المُعدِّل موجودًا ، فلن يساعد الموقف حقًا ، لأن المكتبات لا توثق ما إذا كان المقصود أن تكون الفصول نهائية - على سبيل المثال fs.FSwatcher https://nodejs.org/api/fs.html#fs_class_fs_fswatcher final ؟ يبدو أنه حتى مؤلفو العقدة لا يعرفون. لذا فإن الأمر النهائي كافٍ إذا علم المؤلفون أنه نهائي ، لكن سيتم توثيق ذلك بغض النظر ، وعدم وجود نهائي لا يخبرك حقًا بأي شيء لأنه غالبًا ما يكون غير معروف في كلتا الحالتين.

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذه الرسالة الإلكترونية مباشرةً ، أو قم بعرضها على GitHub https://github.com/Microsoft/TypeScript/issues/8306#issuecomment-458268725 ، أو قم بكتم صوت الموضوع https://github.com/notifications/unsubscribe-auth/AA3NA4o9wu54CcJyK1C8WHVjksIQv3MIP .

نعم ، المناقشة مشتتة للغاية الآن. أود أن أرى هذه المشكلات في أداة تعقب حيث يمكنك التصويت ، مثل تلك المستخدمة في مشكلات IntelliJ / webstorm. احصل على بعض الأرقام الفعلية لعدد الأشخاص الذين يرغبون في رؤية final للفصول و / أو الطرق.

سيكون النهائي مفيدًا جدًا

يتم استخدام كلمة أساسية مجردة لتذكير المبرمجين بضرورة تجاوز المجال. ستكون الكلمة الأساسية لتذكيرهم بعدم تجاوزها مفيدة بطريقة مماثلة.

يمكن أن تكون الطرق النهائية حاسمة في جعل الكود أكثر تنظيمًا و / أو أمانًا.

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

بدون الطرق النهائية ، يمكن أن تتداخل مع وظائفك التي تتحكم في ترتيب العمليات ؛ من المحتمل أن يتسبب في خطأ أو استغلال أو سلوك آخر غير متوقع داخل تطبيقك. في حين أن معظم المواقف سيكون لها نوع من الحل البديل ، يمكن أن تكون هذه الحلول معقدة ومتكررة وأحيانًا لا يمكن الاعتماد عليها ؛ بينما الطرق النهائية تجعلها حلاً بسيطًا عندما يتم تحديد الطريقة.

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

RyanCavanaugh في حين أن هناك مثالًا جيدًا على تقديم () الرغبة في النهاية ، لم يذكر أحد مبدأ Open-Closed (تم اختصاره الآن في المركز الثاني كجزء من SOLID).
من أجل كتابة الأطر التي سيستخدمها الآخرون ، سيكون هذا مفيدًا.
إذا لم يكن الأمر كذلك ، فما هي الطريقة المفضلة لأخذ النهج المفتوح في تنقيط؟

سأحب final للطرق (وأفترض الخصائص والإعلانات بشكل عام). إنه يسبب مشكلة حقيقية - يستمر الناس في تجاوز الأشياء عن طريق الخطأ دون أن يدركوا أن هناك واحدة تحتها ... أشياء تالفة ...

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

وضعي مشابه لـ @ 0815fox حيث لدي نسخة "داخلية" من الطريقة ، وهي مجردة ، لكني أريد ألا يتم تجاوز الإصدار "الأصلي" للطريقة أبدًا ، لأنه يحتوي على سلوك مهم ولا أريده فئة فرعية لتجاوز ذلك.

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

ربما تكون فجوة التوقف هي إضافة معيار إلى TS-Doc حيث يُنصح بعدم ترث فئة معينة أو تجاوز طريقة معينة. مثل التعليق التوضيحي @final أو شيء مشابه.

حسنًا ، ما الذي يجب أن أضيفه إلى ما قاله الآخرون ، الذين صوتوا لـ "نهائي" ... هذا هو تصويتي له.

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

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

يجب أن يكون final هو السبيل للذهاب

العصابة - نظرًا لأن هذه البطاقة (أ) مغلقة ، و (ب) لها عنوان مضلل لمناقشات "الطريقة النهائية" ، فقد قررت إنشاء بطاقة جديدة تركز فقط على الطرق النهائية. نأمل أن يكون من الصعب تجاهل ذلك وقد يحفز بعض التقدم. أوه نعم ، راجع https://github.com/microsoft/TypeScript/issues/33446

تضمين التغريدة

التعقيد مقابل شريط القيمة

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

تضمين التغريدة

كمثال عشوائي ، نقول حاليًا أنه يمكنك أن ترث من أي شيء له توقيع بناء:

// OK
declare const SomeParent: new() => { a: string };
class A extends SomeParent { }

من الواضح أن فئة final هي new -able:

function make<T>(ctor: new() => T) {
  return ctor;
}
final class Done {
}
// No problem
const d = make(Done); // d: Done

ولكن يوجد الآن تناقض: لدينا شيء يمكن أن يكون new -able ، لكن ليس قانونيًا وضعه في عبارة extends . لذا فإن مستوى واحد من المراوغة يهزم final :

function subvertFinal(ctor: new() => any) {
  class Mwhahaah extends ctor {
    constructor() {
      super();
      console.log("I extended a final class! So much for 'types'!")
    }
  }
}
final class Done {
}
subvertFinal(Done);

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

لمعلوماتك 90٪ من الوقت عندما نقول "تعقيد" في هذه المناقشات ، فإننا نعني التعقيد المفاهيمي كما يختبره مستخدمو TypeScript ، وليس تعقيد التنفيذ من جانبنا للغاية من منظور التنفيذ ، على سبيل المثال) ؛ التعقيد المفاهيمي ليس شيئًا يمكنك التعامل معه من خلال إلقاء المزيد من المهندسين وأكثر ذكاءً على المنتج. في كل مرة نضيف شيئًا إلى اللغة يسبب سلوكًا غير متوقع أو يصعب تفسيره ، يكون ذلك عبئًا عقليًا على كل مستخدم للغة.

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

RyanCavanaugh الذي يوضح ذلك حقًا ، شكرًا. رغم ذلك ، أود طرح فكرة: يبدو لي أن المشكلة في المثال الذي قدمته تنشأ بسبب الاقتران القوي بين new و extends ، ربما تكون هذه هي المشكلة الأكبر ، وليس final نفسها. أتساءل لماذا تم اتخاذ قرار الاقتران هذا ، ومدى صعوبة التراجع عنه (لا يعني ذلك على الإطلاق أنه يجب التراجع عنه) في هذه المرحلة.

لست متأكدًا مما إذا كان هذا قد يكون عرضيًا للمناقشة هنا ، على الرغم من ذلك.

هذه مشكلة واجهتني. لا يمكن تجميع نموذج التعليمات البرمجية البسيط هذا.
final keyword ستحل المشكلة تمامًا :

abstract class Parent {
    public abstract method(): this;
}

class Child extends Parent {
    public method(): this {
        return new Child();
    }
}

النوع "تابع" غير قابل للتخصيص لكتابة "هذا".
يمكن تخصيص "الطفل" لقيد من النوع "this" ، ولكن يمكن إنشاء مثيل لـ "this" بنوع فرعي مختلف من القيد "Child".

ملعب

هل يمكن إعادة فتح هذا من فضلك؟ من الواضح أن هناك حاجة لهذه الميزة

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

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

نرحب بالمناقشة البناءة مثل

أنا هنا لدعم إضافة الأساليب النهائية أيضًا. لدي فئة أساسية بوظيفة تسمى _init_ لا أريد أن تتمكن الفئات الفرعية من تجاوزها. سيكون الحل النهائي هو الحل الأمثل.

أنا أؤيد أيضًا إضافة الكلمة الأساسية final للطرق.
في الوقت الحاضر هو معيار في البرمجة الشيئية.

إضافة final أمر منطقي بالنسبة لي. خاصة عند إنشاء مكتبات / أطر عمل للآخرين لاستخدامها ، حيث لا تريد السماح حتى بخطر تجاوز وظيفة.

إذا لم أكن مخطئًا ، فإن إضافة final يمكن أن يساعد في تجنب المتاعب مع أخطاء 'myObj' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'MyClass' عند العمل مع الأدوية العامة لأنني قد أجني MyClass final وبالتالي أضمن ذلك ليست أي أنواع فرعية أخرى.
لست متأكدًا بنسبة 100٪ ولكن أعتقد أن هذه هي الطريقة التي يمكنك بها حل هذه المشكلة في Java.

لدينا نفس العناصر ، نحن نصنع مكونًا أساسيًا في الزاوية التي يمكن أو تحتاج إلى تمديدها كقاعدة هناك الكثير من الحزم الأخرى.
في ذلك ، لدينا أشياء مثل ngOnChanges أو حتى ngOnInit للزاوية التي يجب أن تنفذها الفئة الأساسية فقط ويجب ألا تتجاوز الفئات الفرعية هذه الأشياء ، بل نطبقها في الواقع ngOnInitReal (أو ما نسميه) لذلك نحن مسيطرون تمامًا عندما يتم استدعاء ذلك و بماذا.
لأننا لا نستطيع السيطرة على هذا ، لا يمكننا القيام بذلك إلا من خلال التوثيق. إذا لم يقرأ أحد صانعي المكونات هذا ، فقد يتعطل مكونه ، أو يحتاج إلى نسخ الكثير من التعليمات البرمجية من قاعدتنا للقيام بنفس الشيء ..

لذلك بدون الأساليب النهائية ، لا يمكننا حقًا عمل عقد API صلب.

هل ذكر أحدهم

class Fancy {
    readonly secureFoo = (message: string) => {
        console.log(message);
    }
}

هل ذكر أحدهم

class Fancy {
    readonly secureFoo = (message: string) => {
        console.log(message);
    }
}

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

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