الوراثة في TypeScript: الحصول على معا

مرحبا بالجميع! ينشر فريق TestMace ترجمة أخرى للمقال من عالم تطوير الويب. هذه المرة للمبتدئين! هل لديك قراءة لطيفة.


تحطيم حجاب الغموض وسوء الفهم حول بناء جملة <T> وأخيرا تكوين صداقات معه



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


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


الوراثة في TypeScript


توفر وثائق TypeScript التعريف التالي: "Generics هي القدرة على إنشاء مكونات لا تعمل مع واحد فقط ، ولكن مع أنواع بيانات متعددة."


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


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


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


identity.js
 function identity (value) { return value; } console.log(identity(1)) // 1 

لنجعلها تعمل مع الأرقام:


identity.ts
 function identity (value: Number) : Number { return value; } console.log(identity(1)) // 1 

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


genericIdentity.ts
 function identity <T>(value: T) : T { return value; } console.log(identity<Number>(1)) // 1 

أوه ، هذا بناء جملة <T> غريب! وقف الذعر. نحن فقط نعبر النوع الذي نريد استخدامه لمكالمة دالة محددة.



انظر إلى الصورة أعلاه. عند استدعاء identity<Number>(1) ، يكون نوع Number هو نفس الوسيطة مثل 1. يتم استبداله في كل مكان بـ T يمكن أن تأخذ الدالة عدة أنواع بنفس الطريقة التي تأخذ بها عدة وسيطات.



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


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



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


إيلاء اهتمام خاص للمكالمة الثانية إلى console.log في الرسوم المتحركة أعلاه - لا يتم تمرير النوع إليها. في هذه الحالة ، سيحاول TypeScript حساب النوع من البيانات المرسلة.


فصول عامة واجهات


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


انظر إلى مثال وحاول اكتشاف ذلك بنفسك. اتمنى لك النجاح


genericClass.ts
 interface GenericInterface<U> { value: U getIdentity: () => U } class IdentityClass<T> implements GenericInterface<T> { value: T constructor(value: T) { this.value = value } getIdentity () : T { return this.value } } const myNumberClass = new IdentityClass<Number>(1) console.log(myNumberClass.getIdentity()) // 1 const myStringClass = new IdentityClass<string>("Hello!") console.log(myStringClass.getIdentity()) // Hello! 

إذا لم يتم فهم الكود على الفور ، فحاول تتبع قيم type من الأعلى إلى الأسفل وحتى المكالمات الوظيفية. الإجراء كالتالي:


  1. يتم إنشاء مثيل جديد للفئة IdentityClass ، ويتم تمرير نوع Number والقيمة 1 إليه.
  2. في الفصل ، T تعيين قيمة T للنوع Number .
  3. IdentityClass بتنفيذ GenericInterface<T> ، ونعلم أن T هو Number ، ومثل هذا السجل مكافئ GenericInterface<Number> .
  4. في GenericInterface تصبح U العامة هي Number . في هذا المثال ، استخدمت أسماء متغيرات مختلفة عن قصد لإظهار أن قيمة الكتابة ترتفع في السلسلة وأن اسم المتغير ليس له معنى.

حالات الاستخدام الحقيقي: تجاوز الأنواع البدائية


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


النظر في مثال كلاسيكي للميراث. دعنا نقول لدينا فئة Car ، والتي هي أساس فصول Truck و Vespa . نكتب وظيفة الأداة المساعدة washCar ، والتي تأخذ مثيلًا عامًا من Car وإعادتها.


car.ts
 class Car { label: string = 'Generic Car' numWheels: Number = 4 horn() { return "beep beep!" } } class Truck extends Car { label = 'Truck' numWheels = 18 } class Vespa extends Car { label = 'Vespa' numWheels = 2 } function washCar <T extends Car> (car: T) : T { console.log(`Received a ${car.label} in the car wash.`) console.log(`Cleaning all ${car.numWheels} tires.`) console.log('Beeping horn -', car.horn()) console.log('Returning your car now') return car } const myVespa = new Vespa() washCar<Vespa>(myVespa) const myTruck = new Truck() washCar<Truck>(myTruck) 

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


ستكون نتيجة هذا الرمز:


 Received a Vespa in the car wash. Cleaning all 2 tires. Beeping horn - beep beep! Returning your car now Received a Truck in the car wash. Cleaning all 18 tires. Beeping horn - beep beep! Returning your car now 

لتلخيص


آمل أن أكون ساعدك في التعامل مع الأدوية الجنيسة. تذكر ، كل ما عليك فعله هو تمرير قيمة type إلى الوظيفة :)


إذا كنت ترغب في قراءة المزيد عن الأدوية ، فقد أرفقت ارتباطين أدناه.


ماذا تقرأ :


Source: https://habr.com/ru/post/ar455473/


All Articles