এম্বেডেড বেনাম ইন্টারফেস সহ একটি কাঠামোর অর্থ?


89

sort প্যাকেজ:

type Interface interface {
    Len() int
    Less(i, j int) bool
    Swap(i, j int)
}

...

type reverse struct {
    Interface
}

Interfaceকাঠামোয় বেনামে ইন্টারফেসের অর্থ কী reverse?


অনুসন্ধানকারীদের জন্য এখানে অনেক সহজ ব্যাখ্যা রয়েছে: গোলকিং থেকে আর্কিটেক্টের দৃষ্টিকোণ থেকে একটি নিকট চেহারা । নিবন্ধটির শিরোনাম আপনাকে ভয় দেখাতে দেবেন না। :)
7stud

10
এআইইউআই, এই নিবন্ধটি ("ক্লোজার লুক ...") আসলে বেনামে ইন্টারফেসগুলি কোনও কাঠামোর মধ্যে এম্বেড করার অর্থ কী তা নিয়ে কথা বলছে না, এটি কেবল সাধারণভাবে ইন্টারফেস সম্পর্কে কথা বলে।
অ্যাড্রিয়ান লুডউইন

উত্তর:


72

এই পদ্ধতিতে বিপরীত প্রয়োগ করে sort.Interfaceএবং আমরা অন্য সমস্তকে সংজ্ঞায়িত না করেই একটি নির্দিষ্ট পদ্ধতিকে ওভাররাইড করতে পারি

type reverse struct {
        // This embedded Interface permits Reverse to use the methods of
        // another Interface implementation.
        Interface
}

লক্ষ্য করুন এখানে কীভাবে এটি (j,i)পরিবর্তে পরিবর্তিত হয় (i,j)এবং বাস্তবায়নের reverseপরেও এটি স্ট্রাক্টের জন্য ঘোষিত একমাত্র পদ্ধতিreversesort.Interface

// Less returns the opposite of the embedded implementation's Less method.
func (r reverse) Less(i, j int) bool {
        return r.Interface.Less(j, i)
}

এই পদ্ধতির ভিতরে যেই স্ট্রাক্ট পাস করা হয় আমরা এটিকে নতুন reverseস্ট্রাক্টে রূপান্তর করি ।

// Reverse returns the reverse order for data.
func Reverse(data Interface) Interface {
        return &reverse{data}
}

আসল মানটি আসে যদি আপনি যদি ভাবেন যে এই পদ্ধতির পক্ষে সম্ভব না হয় তবে আপনাকে কী করতে হবে।

  1. একটি অন্য Reverseপদ্ধতি যুক্ত sort.Interface?
  2. আরেকটি রিভার্সইন্টারফেস তৈরি করবেন?
  3. ...?

এই যে কোনও পরিবর্তনের জন্য হাজার হাজার প্যাকেজগুলিতে কোডের আরও অনেক লাইন প্রয়োজন হবে যা স্ট্যান্ডার্ড বিপরীত কার্যকারিতাটি ব্যবহার করতে চায়।


4
সুতরাং এটি আপনাকে একটি ইন্টারফেসের কয়েকটি পদ্ধতির নতুন সংজ্ঞা দিতে দেয়?
ডেভিড 天宇 ওয়াং

4
গুরুত্বপূর্ণ অংশ যে reverseটি সদস্য ধরনের Interface। এর পরে এই সদস্যটির বহিরাগত কাঠামোয় বা অরাইড্রয়েডে এর পদ্ধতিগুলি কলযোগ্য।
ব্রায়ান

এই বৈশিষ্ট্যটি (বা পদ্ধতির) জাভা মাধ্যমে আমরা কী করতে পারি তা অর্জনের উপায় হিসাবে বিবেচনা করা যেতে পারে? extendনন-অ্যাবস্ট্রাক্ট সাব-ক্লাস বাড়ানোর জন্য? আমার কাছে, অভ্যন্তরীণ দ্বারা প্রয়োগ করা বিদ্যমানগুলি ব্যবহার করার সময় কেবলমাত্র কয়েকটি নির্দিষ্ট পদ্ধতিকে ওভাররাইড করার এটি একটি সহজ উপায় হতে পারে Interface
কেভিন ঘাবুসি

তাহলে কি এটি এক ধরণের উত্তরাধিকার? এবং return r.Interface.Less(j, i)অভিভাবক বাস্তবায়ন কল করছে?
ওয়ারওয়ারিয়াক

ইতিমধ্যে দ্বিতীয়বার আমি এই সম্পর্কে বিভ্রান্ত হয়ে পড়েছি। সকল উত্তর এই struct (যা আসলে সাজানোর কিছু প্রয়োজন হয়) এর unintuitive ব্যবহার ভুলবেন বলে মনে হচ্ছে: sort.Sort(sort.Reverse(sort.IntSlice(example)))। আমার জন্য এখানে ব্যথার বিন্দু: পদ্ধতিটি বাছাই বিপরীত কাঠামোতে প্রচারিত হয়, তবে কলটি অ-সদস্য (রিসিভার) স্টাইল।
সবি

41

ঠিক আছে, গৃহীত উত্তরটি আমাকে বুঝতে সাহায্য করেছে, তবে আমি এমন একটি ব্যাখ্যা পোস্ট করার সিদ্ধান্ত নিয়েছি যা আমি মনে করি আমার চিন্তাভাবনার চেয়ে ভাল।

"কার্যকরী যান" এমবেডেড অন্যান্য ইন্টারফেসগুলি থাকার ইন্টারফেসগুলি উদাহরণ রয়েছে:

// ReadWriter is the interface that combines the Reader and Writer interfaces.
type ReadWriter interface {
    Reader
    Writer
}

এবং অন্যান্য কাঠামো এম্বেড থাকা একটি কাঠামো:

// ReadWriter stores pointers to a Reader and a Writer.
// It implements io.ReadWriter.
type ReadWriter struct {
    *Reader  // *bufio.Reader
    *Writer  // *bufio.Writer
}

তবে কোনও ইন্টারফেস এম্বেড করা স্ট্রাক্টের উল্লেখ নেই। এটি sortপ্যাকেজে দেখে আমি বিভ্রান্ত হয়ে পড়েছিলাম :

type Interface interface {
    Len() int
    Less(i, j int) bool
    Swap(i, j int)
}

...

type reverse struct {
    Interface
}

তবে ধারণাটি সহজ। এটি প্রায় একই:

type reverse struct {
    IntSlice  // IntSlice struct attaches the methods of Interface to []int, sorting in increasing order
}

IntSliceউন্নীত করার পদ্ধতিগুলি reverse

এবং এই:

type reverse struct {
    Interface
}

এর অর্থ এটি sort.reverseইন্টারফেস প্রয়োগ করে এমন কোনও কাঠামো এম্বেড করতে পারে sort.Interfaceএবং ইন্টারফেসের যে কোনও পদ্ধতি রয়েছে, সেগুলিতে উন্নীত হবে reverse

sort.Interfaceএমন পদ্ধতি রয়েছে Less(i, j int) boolযা এখন ওভাররাইড করা যেতে পারে:

// Less returns the opposite of the embedded implementation's Less method.
func (r reverse) Less(i, j int) bool {
    return r.Interface.Less(j, i)
}

বোঝার ক্ষেত্রে আমার বিভ্রান্তি

type reverse struct {
    Interface
}

এটাই আমি ভেবেছিলাম যে কোনও স্ট্রাক্টের সর্বদা স্থির কাঠামো থাকে, অর্থাত্ নির্দিষ্ট ধরণের ক্ষেত্রগুলির নির্দিষ্ট সংখ্যা।

তবে নিম্নলিখিতগুলি আমাকে ভুল প্রমাণ করেছে:

package main

import "fmt"

// some interface
type Stringer interface {
    String() string
}

// a struct that implements Stringer interface
type Struct1 struct {
    field1 string
}

func (s Struct1) String() string {
    return s.field1
}


// another struct that implements Stringer interface, but has a different set of fields
type Struct2 struct {
    field1 []string
    dummy bool
}

func (s Struct2) String() string {
    return fmt.Sprintf("%v, %v", s.field1, s.dummy)
}


// container that can embedd any struct which implements Stringer interface
type StringerContainer struct {
    Stringer
}


func main() {
    // the following prints: This is Struct1
    fmt.Println(StringerContainer{Struct1{"This is Struct1"}})
    // the following prints: [This is Struct1], true
    fmt.Println(StringerContainer{Struct2{[]string{"This", "is", "Struct1"}, true}})
    // the following does not compile:
    // cannot use "This is a type that does not implement Stringer" (type string)
    // as type Stringer in field value:
    // string does not implement Stringer (missing String method)
    fmt.Println(StringerContainer{"This is a type that does not implement Stringer"})
}

4
যদি আমার বোধগম্যতা সঠিক হয় তবে ইন্টারফেসের মানগুলি এএ পয়েন্টার দ্বারা নির্ধারিত উদাহরণটিতে এবং উদাহরণের ধরণের পদ্ধতির টেবিলের পয়েন্টার দ্বারা প্রতিনিধিত্ব করা হয়। সুতরাং সমস্ত ইন্টারফেস মান মেমরি একই কাঠামো আছে। কাঠামোগতভাবে, এম্বেডিং রচনা হিসাবে একই। এমনকি কোনও ইন্টারফেস এম্বেড করা স্ট্রাক্টেরও একটি নির্দিষ্ট কাঠামো থাকবে। ইন্টারফেসের পয়েন্টগুলির উদাহরণগুলির কাঠামোগুলি আলাদা হবে।
নিশান্ত জর্জ আগরওয়াল

আমি এটি গ্রহণযোগ্য উত্তরটির চেয়ে আরও ভাল উত্তর পেয়েছি কারণ এটি আরও বিশদ, একটি স্পষ্ট উদাহরণ এবং ডকুমেন্টেশনের লিঙ্ক দিয়েছে।
110100100

28

বিবৃতি

type reverse struct {
    Interface
}

reverseইন্টারফেস প্রয়োগ করে এমন প্রতিটি কিছু দিয়ে আপনাকে আরম্ভ করতে সক্ষম করে Interface। উদাহরণ:

&reverse{sort.Intslice([]int{1,2,3})}

এইভাবে, এমবেড করা Interfaceমান দ্বারা প্রয়োগ করা সমস্ত পদ্ধতি বাইরের দিকে পপুলেটে যায় যখন আপনি এখনও কিছুটিকে ওভাররাইড করতে সক্ষম হন reverse, উদাহরণস্বরূপ Lessবাছাইয়ের বিপরীতে।

এই আসলে ঘটে যখন আপনি ব্যবহার করেন sort.Reverse। আপনি অনুমানের স্ট্রাক্ট বিভাগে এম্বেডিং সম্পর্কে পড়তে পারেন ।


ইতিমধ্যে দ্বিতীয়বার আমি এই সম্পর্কে বিভ্রান্ত হয়ে পড়েছি। সকল উত্তর এই struct (যা আসলে সাজানোর কিছু প্রয়োজন হয়) এর unintuitive ব্যবহার ভুলবেন বলে মনে হচ্ছে: sort.Sort(sort.Reverse(sort.IntSlice(example)))। আমার জন্য এখানে ব্যথার বিন্দু: পদ্ধতিটি বাছাই বিপরীত কাঠামোতে প্রচারিত হয়, তবে কলটি অ-সদস্য (রিসিভার) স্টাইল।
সবি

7

আমি আমার ব্যাখ্যাও দেব। sortপ্যাকেজ একটি unexported টাইপ সংজ্ঞায়িত reverse, যা একটি struct, যে এম্বেড হয় Interface

type reverse struct {
    // This embedded Interface permits Reverse to use the methods of
    // another Interface implementation.
    Interface
}

এটি অন্য ইন্টারফেস প্রয়োগের পদ্ধতিগুলি ব্যবহার করতে বিপরীতকে অনুমতি দেয়। এটি তথাকথিতcomposition যা গোয়ের একটি শক্তিশালী বৈশিষ্ট্য।

Lessজন্য পদ্ধতি reverseকল Lessএমবেডেড পদ্ধতি Interfaceমান, কিন্তু সূচকের সঙ্গে ফ্লিপ সাজানোর ফলাফল ক্রম reversing।

// Less returns the opposite of the embedded implementation's Less method.
func (r reverse) Less(i, j int) bool {
    return r.Interface.Less(j, i)
}

Lenএবং Swapঅন্যান্য দুটি পদ্ধতি reverse, স্পষ্টভাবে মূল Interfaceমান দ্বারা সরবরাহ করা হয় কারণ এটি একটি এমবেডেড ক্ষেত্র। রপ্তানি Reverseফাংশনের একটি দৃষ্টান্ত ফেরৎ reverseযে ধরনের মূল রয়েছে Interfaceমান।

// Reverse returns the reverse order for data.
func Reverse(data Interface) Interface {
    return &reverse{data}
}

আমার কাছে এটি উত্তরাধিকার বলে মনে হচ্ছে। " Lessজন্য পদ্ধতি reverseকল Lessএমবেডেড পদ্ধতি Interfaceমান, কিন্তু সূচকের ফ্লিপ সঙ্গে, সাজানোর ফলাফল ক্রম reversing।" - এটি পিতামাতার বাস্তবায়নের কলিংয়ের মতো দেখায়।
ওয়ারওয়ারিয়াক

যতক্ষণ টাইপ রিভার্সের কেবল একটি ক্ষেত্র রয়েছে যা ইন্টারফেস ইন্টারফেস প্রয়োগ করে এটি ইন্টারফেস ইন্টারফেসের সদস্যও হয়: 0
অ্যালান গুওয়াতুডে

1

আমি এই বৈশিষ্ট্যটি খুব সহায়ক যখন লেখা খুঁজে নিয়ে মশকরা মধ্যে পরীক্ষার

এখানে যেমন একটি উদাহরণ:

package main_test

import (
    "fmt"
    "testing"
)

// Item represents the entity retrieved from the store
// It's not relevant in this example
type Item struct {
    First, Last string
}

// Store abstracts the DB store
type Store interface {
    Create(string, string) (*Item, error)
    GetByID(string) (*Item, error)
    Update(*Item) error
    HealthCheck() error
    Close() error
}

// this is a mock implementing Store interface
type storeMock struct {
    Store
    // healthy is false by default
    healthy bool
}

// HealthCheck is mocked function
func (s *storeMock) HealthCheck() error {
    if !s.healthy {
        return fmt.Errorf("mock error")
    }
    return nil
}

// IsHealthy is the tested function
func IsHealthy(s Store) bool {
    return s.HealthCheck() == nil
}

func TestIsHealthy(t *testing.T) {
    mock := &storeMock{}
    if IsHealthy(mock) {
        t.Errorf("IsHealthy should return false")
    }

    mock = &storeMock{healthy: true}
    if !IsHealthy(mock) {
        t.Errorf("IsHealthy should return true")
    }
}

ব্যবহার করে:

type storeMock struct {
    Store
    ...
}

একজনকে সমস্ত Storeপদ্ধতি উপহাস করার দরকার নেই । শুধুমাত্র HealthCheckউপহাস করা যায়, যেহেতু TestIsHealthyপরীক্ষায় কেবল এই পদ্ধতিটি ব্যবহৃত হয় ।

testআদেশের ফলাফলের নীচে :

$ go test -run '^TestIsHealthy$' ./main_test.go           
ok      command-line-arguments  0.003s

এডাব্লুএস এসডিকে পরীক্ষা করার সময় এই ব্যবহারের কেসটির একটি আসল বিশ্ব উদাহরণ খুঁজে পেতে পারে ।


এটিকে আরও সুস্পষ্ট করার জন্য, এখানে কুরুচিপূর্ণ বিকল্প রয়েছে - Storeইন্টারফেসটি সন্তুষ্ট করার জন্য সর্বনিম্ন একটিকে প্রয়োগ করা দরকার :

type storeMock struct {
    healthy bool
}

func (s *storeMock) Create(a, b string) (i *Item, err error) {
    return
}
func (s *storeMock) GetByID(a string) (i *Item, err error) {
    return
}
func (s *storeMock) Update(i *Item) (err error) {
    return
}

// HealthCheck is mocked function
func (s *storeMock) HealthCheck() error {
    if !s.healthy {
        return fmt.Errorf("mock error")
    }
    return nil
}

func (s *storeMock) Close() (err error) {
    return
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.