هل هناك أي لغات ثابتة مكتوبة على شكل بطة؟
-
08-07-2019 - |
سؤال
هل يمكنني تحديد الواجهات عندما أعلن عضوًا؟
بعد التفكير في هذا السؤال لفترة من الوقت، خطر لي أن اللغة المكتوبة بطريقة البطة الثابتة قد تنجح بالفعل.لماذا لا يمكن ربط الفئات المحددة مسبقًا بواجهة في وقت الترجمة؟مثال:
public interface IMyInterface
{
public void MyMethod();
}
public class MyClass //Does not explicitly implement IMyInterface
{
public void MyMethod() //But contains a compatible method definition
{
Console.WriteLine("Hello, world!");
}
}
...
public void CallMyMethod(IMyInterface m)
{
m.MyMethod();
}
...
MyClass obj = new MyClass();
CallMyMethod(obj); // Automatically recognize that MyClass "fits"
// MyInterface, and force a type-cast.
هل تعرف أي لغة تدعم هذه الميزة؟هل سيكون مفيدًا في Java أو C#؟هل هو معيب بشكل أساسي بطريقة ما؟أتفهم أنه يمكنك فئة فرعية من MyClass وتنفيذ الواجهة أو استخدام نمط تصميم المحول لإنجاز نفس الشيء، ولكن هذه الأساليب تبدو وكأنها تعليمات برمجية نمطية غير ضرورية.
المحلول
واللغات كتبته بشكل ثابت، بحكم التعريف، والتحقق من أنواع في <م> تجميع الوقت م>، وليس <م> تشغيل الوقت م>. واحدة من مشاكل واضحة مع النظام المذكور أعلاه هو أن المترجم هو الذهاب للتحقق أنواع عندما يتم ترجمة البرنامج، وليس في وقت التشغيل.
والآن، هل يمكن بناء المزيد من المعلومات الاستخبارية في المجمع حتى يتسنى لها <م> ينحدر م> أنواع، بدلا من الاضطرار مبرمج <م> صراحة تعلن م> أنواع. المترجم قد يكون قادرا على رؤية أن MyClass
تطبق طريقة MyMethod()
، والتعامل مع هذه الحالة وفقا لذلك، <م> بدون م> الحاجة إلى إعلان صريح واجهات (كما اشرتم). هذا المترجم يمكن الاستفادة نوع الاستدلال، مثل هيندلي-ميلنر .
وبطبيعة الحال، بعض اللغات كتبته بشكل ثابت مثل هاسكل بالفعل لا شيء <م> مماثلة م> لماذا يوحي لك. مترجم هاسكل غير قادرة على استنتاج أنواع (أكثر من مرة) من دون الحاجة إلى إعلان بشكل صريح. ولكن من الواضح، جاوة / C # لا تملك هذه القدرة.
نصائح أخرى
إجابة جديدة لهذا السؤال، Go لديه هذه الميزة بالضبط.أعتقد أنه أمر رائع وذكي حقًا (على الرغم من أنني سأكون مهتمًا برؤية كيف يتم تنفيذه في الحياة الواقعية) وأشاد بالتفكير فيه.
كما هو موثق في الوثائق الرسمية (كجزء من Tour of Go، مع رمز المثال):
يتم تنفيذ واجهات ضمنا
ينفذ النوع واجهة من خلال تنفيذ أساليبه.لا يوجد إعلان صريح عن النية ، لا "تنفذ" الكلمة الرئيسية.
تفصل الواجهات الضمنية تعريف الواجهة عن التنفيذ ، والذي يمكن أن يظهر بعد ذلك في أي حزمة بدون الترتيب المسبق.
وماذا عن استخدام القوالب في C ++؟
class IMyInterface // Inheritance from this is optional
{
public:
virtual void MyMethod() = 0;
}
class MyClass // Does not explicitly implement IMyInterface
{
public:
void MyMethod() // But contains a compatible method definition
{
std::cout << "Hello, world!" "\n";
}
}
template<typename MyInterface>
void CallMyMethod(MyInterface& m)
{
m.MyMethod(); // instantiation succeeds iff MyInterface has MyMethod
}
MyClass obj;
CallMyMethod(obj); // Automatically generate code with MyClass as
// MyInterface
وأنا لم جمعت فعلا هذا الرمز، ولكن أعتقد أنه من عملي وتافهة جدا ج ++ - سعودة من التعليمات البرمجية الأصلية المقترحة (ولكن عدم العمل)
وأنا لا أرى هذه النقطة. لماذا لا تكون واضحة أن الطبقة بتنفيذ واجهة وفعلت معها؟ تنفيذ واجهة ما يقول مبرمجين آخرين أن هذه الفئة من المفترض أن تتصرف بالطريقة تحدد تلك الواجهة. ببساطة وجود نفس الاسم والتوقيع على طريقة ينقل أي ضمانات بأن القصد من مصمم هو تنفيذ إجراءات مماثلة مع الأسلوب. قد يكون ذلك، ولكن لماذا ترك الامر للتفسير (وسوء الاستخدام)؟
والسبب يمكنك ان "الابتعاد" مع ذلك بنجاح في اللغات الديناميكية له علاقة مع TDD من مع اللغة نفسها. في رأيي، إذا كانت اللغة تقدم تسهيلات لإعطاء هذا النوع من التوجيه للآخرين الذين يستخدمون / عرض رمز، يجب عليك استخدامها. في الواقع يحسن من وضوح والجدير قليل من الأحرف الزائدة. في حالة ما إذا لم يكن لديك الوصول إلى القيام بذلك، ثم يعمل محول نفس الغرض إعلان صراحة كيف تتصل واجهة إلى فئة أخرى.
وF # يدعم ثابتة الكتابة بطة، ولكن مع الصيد: لديك لاستخدام القيود الأعضاء. التفاصيل متوفرة في هذا <وأ href = "http://www.atrevido.net/blog/2008/08/31/Statically+Typed+Duck+Typing+In+F.aspx" يختلط = "noreferrer" عنوان = " كتبته بشكل ثابت الكتابة بطة في F # "> دخول بلوق .
مثال من بلوق استشهد:
let inline speak (a: ^a) =
let x = (^a : (member speak: unit -> string) (a))
printfn "It said: %s" x
let y = (^a : (member talk: unit -> string) (a))
printfn "Then it said %s" y
type duck() =
member x.speak() = "quack"
member x.talk() = "quackity quack"
type dog() =
member x.speak() = "woof"
member x.talk() = "arrrr"
let x = new duck()
let y = new dog()
speak x
speak y
ومعظم لغات في دعم الأسرة ML <قوية> أنواع الهيكلية مع الاستدلال ومخططات نوع مقيدة ، أو الذي هو العبقري غريب الأطوار المصطلحات اللغات مصمم الذي يبدو على الأرجح ما تعنيه عبارة "دوك- ثابت الكتابة "في السؤال الأصلي.
لغات أكثر شعبية في هذه العائلة التي تتبادر إلى الذهن ما يلي: هاسكل، الهدف CAML، F # وسكالا. ان واحد الأكثر تطابقا يطابق المثال الخاص بك، بطبيعة الحال، أن يكون الهدف CAML. وفيما يلي ترجمة المثال الخاص بك:
open Printf
class type iMyInterface = object
method myMethod: unit
end
class myClass = object
method myMethod = printf "Hello, world!"
end
let callMyMethod: #iMyInterface -> unit = fun m -> m#myMethod
let myClass = new myClass
callMyMethod myClass
ملحوظة: بعض الأسماء التي استخدمتها وإلى تغيير لتتوافق مع مفهوم لغة كامل الموضوعية للدلالات حالة المعرف، لكن على خلاف ذلك، وهذا هو ترجمة جميلة واضحة
وبالإضافة إلى ذلك، تجدر الإشارة، لا الشرح نوع في وظيفة callMyMethod
ولا تعريف نوع فئة iMyInterface
هو الضرورة القصوى. الهدف CAML أن نستنتج كل شيء في سبيل المثال من دون أي تعريفات نوع على الإطلاق.
حسنا...لذا فهي مجموعة شاملة من جافا سكريبت وربما لا تشكل "لغة"، ولكن هذا النوع من كتابة البطة الثابتة أمر حيوي في TypeScript.
وبو بالتأكيد هي لغة كتبته بطة ثابتة: http://boo.codehaus.org/Duck + كتابة
ومقتطفات:
<اقتباس فقرة>وبو هي لغة كتابتها بشكل ثابت، مثل جافا أو C #. وهذا يعني بو الخاص سيتم تشغيل تطبيقات حول بأسرع تلك مشفرة في الآخر كتبته بشكل ثابت اللغات .NET أو مونو. ولكن باستخدام لغة كتابتها بشكل ثابت في بعض الأحيان يحد لك إلى غير مرنة و مطول الترميز أسلوب، مع أحيانا تعريفات نوع ضروري (مثل "س ك int"، ولكن هذا ليس غالبا ما يكون ضروريا بسبب نوع بو ل الاستدلال) وضرورية في بعض الأحيان نوع يلقي (انظر أنواع الصب). لبوو الدعم لنوع الاستدلال و في نهاية المطاف الوراثة مساعدة هنا، ولكن ...
وأحيانا يكون من المناسب أن تتخلى شبكة الأمان التي توفرها ثابت الكتابة. ربما كنت ترغب فقط في استكشاف وAPI دون القلق كثيرا عن تواقيع طريقة أو ربما كنت خلق التعليمات البرمجية التي يتحدث الخارجية مكونات مثل الكائنات COM. إما الطريقة التي ينبغي أن يكون الخيار لك لا الألغام.
وجنبا إلى جنب مع أنواع طبيعية مثل الكائن، الباحث، سلسلة ... بو لديه نوع خاص يسمى "البطة". المصطلح مستوحاة من البرمجة روبي ميزة بطة كتابة اللغة في ( "إذا كان يمشي مثل البطة والدجالون مثل بطة، يجب أن يكون بطة ").
اقتباس فقرة>وإصدارات جديدة من C ++ التحرك في اتجاه ثابت الكتابة بطة. يمكنك في يوم من الأيام (؟ اليوم) كتابة شيء من هذا القبيل:
auto plus(auto x, auto y){
return x+y;
}
وسيكون تفشل في تجميع اذا لم يكن هناك استدعاء دالة مطابقة لx+y
.
وأما بالنسبة لنقدك:
<اقتباس فقرة> يتم إنشاءوA "CallMyMethod" جديدة لكل نوع من أنواع مختلفة يمكنك تمرير لها، حتى انها لم تكتب حقا الاستدلال.
اقتباس فقرة> ولكن من نوع الاستدلال (يمكنك أن تقول foo(bar)
حيث foo
هي وظيفة قالب)، ولها نفس التأثير، إلا أنها أكثر كفاءة من الوقت ويأخذ مساحة أكبر في التعليمات البرمجية المترجمة.
وعلى خلاف ذلك، سيكون لديك للبحث عن طريقة أثناء وقت التشغيل. عليك أن تجد اسما، ثم تأكد من أن اسم ديه طريقة مع المعلمات الصحيحة.
وأو هل لديك لتخزين كل تلك المعلومات حول مطابقة واجهات، والنظر في كل فئة يطابق واجهة، ثم تضاف تلقائيا تلك الواجهة.
في كلتا الحالتين، التي تسمح لك ضمنيا ودون قصد لكسر التسلسل الهرمي فئة، وهو شر ميزة جديدة لأنه يتعارض مع عادات ما تستخدم المبرمجين C # / جافا ل. مع قوالب C ++، كنت تعرف أنك في حقل ألغام (وهم أيضا إضافة ميزة ( "مفاهيم") للسماح قيود على المعلمات القالب).
وأنواع الهيكلية في سكالا يفعل شيئا من هذا القبيل.
وانظر <لأ href = "http://web.archive.org/web/20090818051106/http://neilbartlett.name/blog/2007/09/13/statically-checked-duck-typing-in-scala / "يختلط =" نوفولو noreferrer "> تم الفحص بشكل ثابت" بطة الكتابة "في سكالا
وكان تصميم ما قبل النشر لمدة 9 البصرية الأساسية لدعم ساكنة الكتابة البط باستخدام واجهات دينامية لكن قطعوا ميزة <لأ href = "http://www.infoq.com/news/2007/04/Dynamic-Interface "يختلط =" نوفولو noreferrer "> * من أجل شحن في الوقت المحدد.
D ( http://dlang.org ) هو لغة مترجمة بشكل ثابت ويوفر بطة الكتابة عبر التفاف () وبسط () ( http://dlang.org/phobos-prerelease/std_typecons.html # .unwrap ).
ويبدو وكأنه Mixins أو الصفات:
http://en.wikipedia.org/wiki/Mixin
http://www.iam.unibe.ch/~scg/ الأرشيف / أوراق عمل / Scha03aTraits.pdf
في أحدث نسخة من لغة البرمجة بي هيرون أنها تدعم شيئا من هذا القبيل من خلال الإكراه التصنيف الفرعي لالبنيوي دعا المشغل as
. وذلك بدلا من:
MyClass obj = new MyClass();
CallMyMethod(obj);
ويمكنك أن تكتب:
MyClass obj = new MyClass();
CallMyMethod(obj as IMyInterface);
وكما هو الحال في المثال الخاص بك، في هذه الحالة MyClass
لم يكن لديك لتنفيذ صراحة IMyInterface
، ولكن إذا فعلت المدلى بها يمكن أن يحدث ضمنيا ويمكن حذف المشغل as
.
ولقد كتبت أكثر قليلا عن الأسلوب الذي أسميه صريحة الهيكلية الفرعية الكتابة في <لأ href = "http://dobbscodetalk.com/index.php؟option=com_myblog&show=Explicit-Structural-Typing-Duck-Typing -.html & Itemid = 29 "يختلط =" نوفولو noreferrer "> هذه المقالة .