ইন্টারফেস ক্ষেত্র যান


105

আমি গো-তে ইন্টারফেসগুলি ডেটা না দিয়ে কার্যকারিতা সংজ্ঞায়িত করে তার সাথে আমি পরিচিত। আপনি একটি ইন্টারফেসে পদ্ধতির একটি সেট রেখেছেন, তবে আপনি কোনও ইন্টারফেস প্রয়োগ করে এমন কোনও ক্ষেত্র নির্দিষ্ট করতে অক্ষম।

উদাহরণ স্বরূপ:

// Interface
type Giver interface {
    Give() int64
}

// One implementation
type FiveGiver struct {}

func (fg *FiveGiver) Give() int64 {
    return 5
}

// Another implementation
type VarGiver struct {
    number int64
}

func (vg *VarGiver) Give() int64 {
    return vg.number
}

এখন আমরা ইন্টারফেস এবং এর প্রয়োগগুলি ব্যবহার করতে পারি:

// A function that uses the interface
func GetSomething(aGiver Giver) {
    fmt.Println("The Giver gives: ", aGiver.Give())
}

// Bring it all together
func main() {
    fg := &FiveGiver{}
    vg := &VarGiver{3}
    GetSomething(fg)
    GetSomething(vg)
}

/*
Resulting output:
5
3
*/

এখন, আপনি যা করতে পারবেন না তা এরকম কিছু:

type Person interface {
    Name string
    Age int64
}

type Bob struct implements Person { // Not Go syntax!
    ...
}

func PrintName(aPerson Person) {
    fmt.Println("Person's name is: ", aPerson.Name)
}

func main() {
    b := &Bob{"Bob", 23}
    PrintName(b)
}

যাইহোক, ইন্টারফেস এবং এমবেডেড স্ট্রাক্টগুলি নিয়ে ঘুরে দেখার পরে, আমি এটি করার একটি উপায় আবিষ্কার করেছি, ফ্যাশন পরে:

type PersonProvider interface {
    GetPerson() *Person
}

type Person struct {
    Name string
    Age  int64
}

func (p *Person) GetPerson() *Person {
    return p
}

type Bob struct {
    FavoriteNumber int64
    Person
}

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

func DoBirthday(pp PersonProvider) {
    pers := pp.GetPerson()
    pers.Age += 1
}

func SayHi(pp PersonProvider) {
    fmt.Printf("Hello, %v!\r", pp.GetPerson().Name)
}

func main() {
    b := &Bob{
        5,
        Person{"Bob", 23},
    }
    DoBirthday(b)
    SayHi(b)
    fmt.Printf("You're %v years old now!", b.Age)
}

এখানে একটি গো খেলার মাঠ যা উপরের কোডটি প্রদর্শন করে।

এই পদ্ধতিটি ব্যবহার করে, আমি এমন একটি ইন্টারফেস তৈরি করতে পারি যা আচরণের চেয়ে ডেটা সংজ্ঞা দেয় এবং যা কেবল কোনও ডেটা এম্বেড করে কোনও স্ট্রাক্ট দ্বারা প্রয়োগ করা যেতে পারে। আপনি এমন ফাংশনগুলি সংজ্ঞায়িত করতে পারেন যা এম্বেড হওয়া ডেটার সাথে স্পষ্টভাবে ইন্টারঅ্যাক্ট করে এবং বাহ্যিক কাঠামোর প্রকৃতি সম্পর্কে অজানা। এবং সবকিছু সংকলনের সময় চেক করা হয়! (শুধুমাত্র আপনি জগাখিচুড়ি আপ, আমি দেখতে পাচ্ছি পারে, ইন্টারফেস এম্বেডিং করা হবে PersonProviderBobবরং একটি কংক্রিট চেয়ে Person। এটি কম্পাইল এবং রানটাইম এ ব্যর্থ হবে।)

এখন, এখানে আমার প্রশ্ন: এটি কি একটি ঝরঝরে কৌশল, না আমার অন্যভাবে করা উচিত?


3
"আমি এমন একটি ইন্টারফেস তৈরি করতে পারি যা আচরণের চেয়ে ডেটা সংজ্ঞায়িত করে"। আমি যুক্তি দিয়ে বলব যে আপনার এমন একটি আচরণ রয়েছে যা ডেটা ফেরত দেয়।
জামালনি

আমি একটি উত্তর লিখতে যাচ্ছি; আমি মনে করি এটি ঠিক আছে যদি আপনার এটির প্রয়োজন হয় এবং এর পরিণতিগুলি জেনে থাকেন তবে ফলাফলগুলি রয়েছে এবং আমি এটি সর্বদা করতাম না।
twotwotwo

@ জামলনি আমার মনে হয় আপনি ঠিক বলেছেন, যদি আপনি এটিকে স্পষ্টভাবে দেখতে চান। তবে সামগ্রিকভাবে, আমি দেখানো বিভিন্ন টুকরো দিয়ে শব্দার্থবিজ্ঞানগুলি "এই ফাংশনটি এমন কোনও কাঠামো গ্রহণ করে যার গঠনতে ___ রয়েছে"। কমপক্ষে, আমি যা চেয়েছিলাম সেটাই ছিল।
ম্যাট ম্যাক 0

1
এটি "উত্তর" উপাদান নয়। "স্ট্রাক্ট প্রোপার্টি গোলং হিসাবে ইন্টারফেস" গুগল করে আমি আপনার প্রশ্নে পৌঁছেছি। আমি একটি স্ট্রাক সেট করে অনুরূপ পন্থা পেয়েছি যা অন্য স্ট্রাক্টের সম্পত্তি হিসাবে একটি ইন্টারফেস প্রয়োগ করে। এখানে খেলার মাঠ, play.golang.org/p/KLzREXk9xo আমাকে কিছু ধারণা দেওয়ার জন্য ধন্যবাদ।
ডেল

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

উত্তর:


55

এটি অবশ্যই একটি ঝরঝরে কৌশল। তবে, উন্মুক্ত পয়েন্টারগুলি এখনও ডেটাতে সরাসরি অ্যাক্সেস উপলব্ধ করে, তাই এটি কেবল ভবিষ্যতের পরিবর্তনের জন্য আপনাকে সীমিত অতিরিক্ত নমনীয়তা ক্রয় করে। এছাড়াও, গো কনভেনশনগুলির জন্য আপনাকে সর্বদা আপনার ডেটা বৈশিষ্ট্যের সামনে বিমূর্ততা রাখার প্রয়োজন হয় না

এই জিনিসগুলি একসাথে নিয়ে যাওয়া, আমি একটি প্রদত্ত ব্যবহারের ক্ষেত্রে চূড়ান্ত বা অন্যটির দিকে ঝুঁকছি: হয় ক) কেবলমাত্র একটি সর্বজনীন বৈশিষ্ট্য তৈরি করুন (প্রযোজ্য ক্ষেত্রে এম্বেডিং ব্যবহার করে) এবং কংক্রিটের প্রকারগুলি পাস করুন বা খ) যদি তথ্যটি প্রকাশ করার মতো মনে হয় পরে সমস্যা সৃষ্টি করুন, আরও শক্তিশালী বিমূর্ততার জন্য একজন গেটর / সেটারকে প্রকাশ করুন।

আপনি প্রতি-গুণ অনুসারে এটি ওজন করতে যাচ্ছেন। উদাহরণস্বরূপ, যদি কিছু ডেটা বাস্তবায়ন-নির্দিষ্ট হয় বা আপনি অন্য কোনও কারণে উপস্থাপনা পরিবর্তন করার প্রত্যাশা করেন তবে আপনি সম্ভবত এট্রিবিউটটি সরাসরি প্রকাশ করতে চান না, অন্য ডেটা অ্যাট্রিবিউটগুলি এটিকে সার্বজনীন করে তোলা যে নেট জয় net


গেটার এবং সেটটারের পিছনে সম্পত্তি গোপন করা আপনাকে পিছনে সামঞ্জস্যপূর্ণ পরিবর্তনগুলি করার জন্য কিছু অতিরিক্ত নমনীয়তা দেয়। বলুন যে Personকোনও দিন আপনি কেবল একটি একক "নাম" ক্ষেত্র নয়, প্রথম / মধ্য / শেষ / উপসর্গ সংরক্ষণ করতে চান; আপনার যদি পদ্ধতি থাকে Name() stringএবং SetName(string), Personনতুন সূক্ষ্ম-দানযুক্ত পদ্ধতি যুক্ত করার সময় আপনি ইন্টারফেসের বিদ্যমান ব্যবহারকারীদের খুশি রাখতে পারেন । অথবা আপনি কোনও ডাটাবেস-ব্যাকড অবজেক্টটিকে "নোংরা" হিসাবে চিহ্নিত করতে সক্ষম হতে চাইবেন যখন এটি সংরক্ষণ না করা পরিবর্তনগুলি করেছে; আপনি যখন তা করতে পারেন যখন ডেটা আপডেটগুলি সমস্ত SetFoo()পদ্ধতির মধ্য দিয়ে যায় ।

সুতরাং: গিটার্স / সেটটারগুলির সাহায্যে আপনি সামঞ্জস্যপূর্ণ এপিআই বজায় রেখে স্ট্রাক্ট ক্ষেত্রগুলি পরিবর্তন করতে পারেন এবং সম্পত্তি পেতে / সেটগুলির আশেপাশে যুক্তি যুক্ত করতে পারেন কারণ p.Name = "bob"আপনার কোডটি না দিয়ে কেউই পারবে না ।

টাইপটি জটিল হওয়ার সময় এই নমনীয়তাটি আরও প্রাসঙ্গিক হয় (এবং কোডবেস বড় হয়)। আপনার যদি একটি থাকে তবে PersonCollectionএটি অভ্যন্তরীণভাবে একটি sql.Rows, ক []*Person, একটি []uintডাটাবেস আইডি, বা যে কোনও কিছু দ্বারা ব্যাক করা যেতে পারে । সঠিক ইন্টারফেস ব্যবহার করে, আপনি কলারদের এটি দেখাশোনা থেকে বাঁচাতে পারেন, উপায়টি io.Readerনেটওয়ার্ক সংযোগ এবং ফাইলগুলিকে একরকম দেখায়।

একটি সুনির্দিষ্ট জিনিস: interfaceগো-এর অদ্ভুত সম্পত্তি রয়েছে যা আপনি যে প্যাকেজটিকে সংজ্ঞায়িত করে তা আমদানি না করেই একটি প্রয়োগ করতে পারবেন; যা আপনাকে চক্রীয় আমদানি এড়াতে সহায়তা করতে পারে । যদি আপনার ইন্টারফেসটি *Personকেবল স্ট্রিং বা যা কিছু পরিবর্তে একটি ফেরত PersonProvidersদেয় , সকলকে প্যাকেজটি যেখানে সংজ্ঞাযুক্ত তা আমদানি করতে হবে Person। এটি সূক্ষ্ম বা এমনকি অনিবার্য হতে পারে; এটি সম্পর্কে জানা মাত্র একটি পরিণতি।


তবে আবার, গো সম্প্রদায়ে আপনার ধরণের পাবলিক এপিআই তে ডেটা সদস্যদের এক্সপোজ করার বিরুদ্ধে একটি শক্তিশালী কনভেনশন নেই । এটা আপনার রায় বাকি কিনা এটা একটি বৈশিষ্ট্য থেকে পাবলিক এক্সেস বরং নিরুৎসাহিত করার পরিবর্তে, একটি প্রদত্ত ক্ষেত্রে আপনার API- এর অংশ হিসাবে ব্যবহার করার জন্য যুক্তিসঙ্গত এর কোনো এক্সপোজার কারণ এটি সম্ভবত জটিল করে তুলতে পারে বা একটি বাস্তবায়ন পরিবর্তন করে পরে প্রতিরোধ।

সুতরাং, উদাহরণস্বরূপ, stdlib আপনাকে http.Serverআপনার কনফিগারেশনের মাধ্যমে একটি আরম্ভ করতে দেয় এবং প্রতিশ্রুতি দেয় যে একটি শূন্য bytes.Bufferব্যবহারযোগ্য। আপনার নিজের স্টাফগুলি সেভাবে করা ভাল এবং সত্যই, আমি মনে করি না যদি আরও কংক্রিট, ডেটা-এক্সপোজারিং সংস্করণটি কাজ করে বলে মনে হয় তবে আপনার পূর্ববর্তী জিনিসগুলি বিমূর্ত করা উচিত। এটি কেবল বাণিজ্য সম্পর্কে সচেতন হওয়া সম্পর্কে।


একটি অতিরিক্ত জিনিস: এম্বেডিং পদ্ধতিটি খানিকটা উত্তরাধিকারের মতো, তাই না? এমবেডড স্ট্রাক্টের যে কোনও ক্ষেত্র এবং পদ্ধতি আপনি পেয়েছেন এবং আপনি এর ইন্টারফেসটি ব্যবহার করতে পারেন যাতে কোনও সুপারস্ট্রাট ইন্টারফেসের সেটগুলি পুনরায় বাস্তবায়ন না করে যোগ্যতা অর্জন করতে পারে।
ম্যাট ম্যাক

হ্যাঁ - অন্যান্য ল্যাংগুলিতে অনেকটা ভার্চুয়াল উত্তরাধিকারের মতো। আপনি কোনও ইন্টারফেস বাস্তবায়নের জন্য এম্বেডিং ব্যবহার করতে পারেন এটি গ্রাহকগণ এবং সেটারের ক্ষেত্রে বা ডেটারের পয়েন্টারের ক্ষেত্রে সংজ্ঞায়িত করা হয়েছে (বা, ক্ষুদ্রতর স্ট্রোকগুলিতে কেবলমাত্র পাঠ্য অ্যাক্সেসের জন্য তৃতীয় বিকল্প, কাঠামোর অনুলিপি)।
twotwotwo

আমার বলতে হবে, এটি আমাকে 1999-এ ফ্ল্যাশব্যাক দিচ্ছে এবং জাভাতে বয়লারপ্লেট গেটার এবং সেটটারের রিমগুলি লিখতে শিখছে।
টম

এটি খুব খারাপ গো এর নিজস্ব স্ট্যান্ডার্ড লাইব্রেরি সর্বদা এটি করে না। আমি ওএস এর জন্য কিছু কল উপহাস করার চেষ্টা করার মাঝখানে আছি unit ইউনিট পরীক্ষার জন্য প্রসেস করুন। আমি কেবলমাত্র একটি ইন্টারফেসে প্রক্রিয়া অবজেক্টটি গুটিয়ে রাখতে পারি না যেহেতু পিড সদস্য ভেরিয়েবলটি সরাসরি অ্যাক্সেস করা হয় এবং গো ইন্টারফেসগুলি সদস্য ভেরিয়েবলগুলিকে সমর্থন করে না।
অ্যালেক্স জ্যানসেন

1
@ টম এটি সত্য। আমি getters / setters একটি পয়েন্টার প্রকাশক চেয়ে আরো নমনীয়তা যোগ মনে করেন, কিন্তু আমি আরো মনে করি না প্রত্যেকের উচিত সংগ্রহকারী / সেটার-ify সবকিছু (অথবা টিপিক্যাল যান শৈলী মেলে যে)। আমার এর আগে ইশারায় কয়েকটি শব্দ ছিল তবে এটি আরও জোর দেওয়ার জন্য শুরু এবং শেষের সংশোধন করেছি।
twotwotwo

2

আমি যদি সঠিকভাবে বুঝতে পারি তবে আপনি একটি কাঠামো ক্ষেত্রকে অন্য একটিতে স্থাপন করতে চান। আমার মতামত প্রসারিত করার জন্য ইন্টারফেস ব্যবহার করবেন না। আপনি সহজেই পরবর্তী পদ্ধতির মাধ্যমে এটি করতে পারেন।

package main

import (
    "fmt"
)

type Person struct {
    Name        string
    Age         int
    Citizenship string
}

type Bob struct {
    SSN string
    Person
}

func main() {
    bob := &Bob{}

    bob.Name = "Bob"
    bob.Age = 15
    bob.Citizenship = "US"

    bob.SSN = "BobSecret"

    fmt.Printf("%+v", bob)
}

https://play.golang.org/p/aBJ5fq3uXtt

উল্লেখ্য Personমধ্যে Bobঘোষণা। এটি অন্তর্ভুক্ত স্ট্রাক্ট ক্ষেত্রটি Bobকিছু সিনট্যাকটিক চিনির সাথে সরাসরি কাঠামোতে উপলব্ধ করা হবে ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.