كيفية إغلاق خاصية متوجهة
-
30-09-2019 - |
سؤال
لنفترض أن لدي زوجًا من فصول C# مفتعلة بشكل واضح مثل هذا:
public abstract class Foo {
public abstract int[] LegalValues { get; }
public virtual bool IsValueLegal(int val) {
return Array.IndexOf(LegalValues, val) >= 0;
}
}
وهذا:
public class Bar : Foo {
static int[] _legalValues = new int[] { 0, 1 }; // whatever
public sealed override int[] LegalValues
{ get { return _legalValues; } }
public sealed override bool IsValueLegal(int val)
{ return base.IsValueLegal(val); }
}
كيف أفعل هذا في F#؟ الرمز الواضح للخصائص:
[<Sealed>]
override this.LegalValues with get() = // ...
[<Sealed>]
override this.IsValueLegal value = // ...
يؤدي إلى خطأ لأنه لا يمكن تطبيق Sealedattribute على الأعضاء. بالطبع ، يمكنني إغلاق الفصل بأكمله وبالتالي ختم جميع الأعضاء ، ولكن (وهذا هو مهم للغاية ولكن) هو أن لدي هدف لمطابقة توقيع الطبقة الحالية بالضبط والفئة الأساسية لديها أعضاء افتراضي/مجردة آخرين يجب ، من الناحية المثالية ، أن يظلوا على عاتق.
المحلول
يوجد حاليًا العديد من القيود على دعم F# لـ OO ، لذلك لا ينبغي أن تتوقع عمومًا أن تكون قادرًا على إنتاج تسلسل هرمي فئة F# وهو مطابق لتسلسل هرمي تعسفي C#. على حد علمي ، لا توجد طريقة لتجاوز وإغلاق طريقة افتراضية.
نصائح أخرى
يبدو أن f# يحدد سمة مختومة يتم تعريفه باستخدام خاصية AttributeTargets الخاصة به على الفصل فقط ، وربما لا يمكن إغلاق الأعضاء.
هذا ربما موافق, ، نظرًا لأن الوراثة والوظائف الغالبة تكون بشكل عام أقل من ذكاءات F# من C#. لا أعتقد أنه يمكنك حقًا الحصول على ما تريد دون إعادة الكتابة في المزيد من التعابير. ابدأ بهذا:
type foo =
| Bar
| Baz
| Qux
with
member this.LegalValues =
match this with
| Bar -> [0; 1]
| Qux -> [-1; 0; 1]
| Baz -> [0 .. 10 ]
member this.IsValueLegal value =
match this with
| Baz -> value >= 0 && value <= 10
| _ -> List.exists (fun x -> x = value) (this.LegalValues)
تستطيع قول ذلك Baz
"تجاوز" foo.IsValueLegal
عضو ، جميع الأنواع الأخرى تستخدم وظيفة "القاعدة".