سؤال

في سكالا ، يمكنني تحديد الأنواع الهيكلية على النحو التالي:

type Pressable = { def press(): Unit }

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

def foo(i: Pressable) { // etc.

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

يمكنني حتى استخدام النوع الهيكلي:

def foo(i: { def press(): Unit }) { // etc.

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

هل C# لديه شيء مشابه؟ لقد غوغل لكنني لا أجد أي شيء ، لكنني لست على دراية بـ C# في أي عمق. إذا لم يكن هناك ، هل هناك أي خطط لإضافة هذا؟

هل كانت مفيدة؟

المحلول

لا ، ولا توجد خطط أعرفها. فقط اسم (بدلاً من الهيكلية) الفرعية (مثل الواجهات).

(قد يرغب الآخرون في رؤية أيضًا

http://en.wikipedia.org/wiki/nominative_type_system

http://en.wikipedia.org/wiki/structural_type_system

)

(قد يشير عدد قليل من الناس إلى بعض حالات الزاوية الغريبة ، مثل foreach بيان باستخدام الكتابة الهيكلية ل GetEnumerator, ، لكن هذا هو استثناء بدلا من القاعدة.)

نصائح أخرى

لا توجد طريقة لتحديد الأنواع الهيكلية التي لها وظيفة معينة. هناك مكتبة تضيف دعم كتابة البط إلى C# يمكن العثور عليها هنا.

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

public interface ICanAdd
{
    int Add(int x, int y);
}

// Note that MyAdder does NOT implement ICanAdd, 
// but it does define an Add method like the one in ICanAdd:
public class MyAdder
{
    public int Add(int x, int y)
    {
        return x + y;
    }
}

public class Program
{
    void Main()
    {
        MyAdder myAdder = new MyAdder();

        // Even though ICanAdd is not implemented by MyAdder, 
        // we can duck cast it because it implements all the members:
        ICanAdd adder = DuckTyping.Cast<ICanAdd>(myAdder);

        // Now we can call adder as you would any ICanAdd object.
        // Transparently, this call is being forwarded to myAdder.
        int sum = adder.Add(2, 2);
    }
}

هذه هي الطريقة C# لتحقيق نفس الشيء باستخدام واجهات OL الممل الجيدة.

interface IPressable {
  void Press();
}

class Foo {
 void Bar(IPressable pressable) {
    pressable.Press();
 }
}

class Thingy : IPressable, IPushable, etc {
 public void Press() {
 }
}

static class Program {
 public static void Main() {
  pressable = new Thingy();
  new Foo().Bar(pressable);
 }
}

كما لاحظ آخرون ، هذا ليس كذلك هل حقا متوفر في .NET (لأن هذا مسألة وقت التشغيل أكثر من لغة). ومع ذلك ، يدعم .NET 4.0 شيء مماثل لواجهات COM المستوردة وأعتقد أن هذا يمكن استخدامه لتنفيذ الكتابة الهيكلية لـ .NET. شاهد منشور المدونة هذا:

لم أحاول اللعب مع هذا بنفسي بعد ، لكنني أعتقد أنه قد يمكّن مؤلفي برنامج التحويل البرمجي من كتابة اللغات مع الكتابة الهيكلية لـ .NET. (الفكرة هي أن أنت (أو مترجم) ستحدد واجهة خلف المشهد ، لكنها ستعمل ، لأن الواجهات ستتعامل مع معادلة بفضل ميزة معادلة com).

أيضا ، C# 4.0 يدعم dynamic الكلمة الرئيسية التي ، على ما أعتقد ، يمكن تفسيرها على أنها كتابة هيكلية (بدون فحص نوع ثابت). تتيح لك الكلمة الرئيسية استدعاء طرق على أي كائن دون معروف (في وقت الترجمة) ما إذا كان الكائن سيكون له الطرق المطلوبة. هذا هو نفس الشيء مثل مشروع "كتابة البط" التي ذكرها IGOR (ولكن هذا ، بالطبع ، ليس كتابة هيكلية مناسبة).

ربما يمكن تفسير النمط القابل للانتظار في C# على أنه مثال محدود ومخصص للكتابة الفرعية الهيكلية / الوجودية. سوف المترجم فقط await الكائنات التي لديها إمكانية الوصول إلى GetAwaiter() الطريقة التي تعيد أي INotifyCompletion كائن مع مجموعة محددة من الأساليب والخصائص. نظرًا لأن الكائن "القابل للانتظار" أو الكائن "ينتظر" يحتاج إلى تنفيذ أي واجهة (باستثناء INotifyCompletion في حالة الأخير) ، await يشبه الطريقة التي تقبل كائنات مكتوبة هيكلياً.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top