pointers أنواع أساليب هيكل الذهاب التي تلبي واجهة




go methods (2)

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

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

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

انظر هذه الإجابة التي تفاصيل / يثبت أن القيم يتم نسخ عند إنشاء قيمة واجهة: كيف يمكن شريحة تحتوي على نفسها؟

وبالنظر إلى مثال كود غو التالي:

package main

import "fmt"

type greeter interface {
    hello()
    goodbye()
}

type tourGuide struct {
    name string
}

func (t tourGuide) hello() {
    fmt.Println("Hello", t.name)
}

func (t *tourGuide) goodbye() {
    fmt.Println("Goodbye", t.name)
}

func main() {
    var t1 tourGuide = tourGuide{"James"}
    t1.hello()   // Hello James
    t1.goodbye() // Goodbye James (same as (&t1).goodbye())

    var t2 *tourGuide = &tourGuide{"Smith"}
    t2.hello()   // Hello Smith
    t2.goodbye() // Goodbye Smith (same as (*t2).hello())

    // illegal: t1 is not assignable to g1 (why?)
    // var g1 greeter = t1

    var g2 greeter = t2
    g2.hello()   // Hello Smith
    g2.goodbye() // Goodbye Smith
}

أنا قادرة على استدعاء طريقتين من tourGuide باستخدام إما متغير من نوع تورغيد t1 أو مؤشر ل تورغيد t2 . وبعبارة أخرى، يمكنني استدعاء طريقة مع T استقبال باستخدام متغير من نوع T أو *T وبالمثل، يمكنني استدعاء طريقة مع *T استقبال باستخدام متغير من نوع T (إذا كان T هو عنوان ) أو *T وأنا أفهم أن معدي البيانات يعالج الاختلافات هنا (انظر تعليقاتي في الشفرة).

ومع ذلك، تتغير الأمور عندما نقوم بتنفيذ واجهات. في التعليمات البرمجية أعلاه، متغير من واجهة نوع greeter هو تخصيص من مؤشر إلى tourGuide ولكن ليس من tourGuide .

هل يمكن لأحد أن يقول لي لماذا هذا هو الحال؟ لماذا أنا قادرة على استدعاء t1.hello() و t1.goodbye() ولكن على نحو ما t1 لا يكفي ل greeter واجهة؟


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

package main

import "fmt"

type greeter interface {
    hello()
    goodbye()
}

type tourGuide struct {
    name string
}

func (t tourGuide) hello() {
    fmt.Println("Hello", t.name)
}

func (t *tourGuide) goodbye() {
    fmt.Println("Goodbye", t.name)
}

func main() {
    var t1 tourGuide = tourGuide{"James"}
    t1.hello()   // Hello James
    t1.goodbye() // Goodbye James (same as (&t1).goodbye())

    var tmpT2 *tourGuide = &tourGuide{"Smith"}
    var t2 **tourGuide = &tmpT2
    (*t2).hello()   // Hello Smith
    (*t2).goodbye() // Goodbye Smith (same as (*t2).hello())

    //illegal: t1 is not assignable to g1 (why?)
    //var g1 greeter = t1

    //now this is illegal too
    //var g2 greeter = t2

    var g3 greeter = (*t2)
    g3.hello()   // Hello Smith
    g3.goodbye() // Goodbye Smith
}




interface