دستیابی به برنامه نویسی شی گرا در Go آنقدرها هم که فکر می کنید سخت نیست.
برنامه نویسی شی گرا (OOP) یک پارادایم برنامه نویسی است که بر اساس اشیا به عنوان مفهوم اصلی است. در OOP، کد بر اساس عملکرد، امکان نگهداری کد، انتزاع، قابلیت استفاده مجدد، کارایی و قابلیت های متعدد روی شی قالب بندی می شود.
شی دارای ویژگیهایی (متغیرها) است که ویژگیها، ویژگیها و روشها (توابع) آن را تعریف میکنند که اعمال (رویهها) و رفتارهای شی را تعریف میکنند.
برنامه نویسی شی گرا در Go با زبان های دیگر متفاوت است. مفاهیم شی گرا در Go با استفاده از ساختارها، رابط ها و انواع سفارشی پیاده سازی می شوند.
سفارشی کردن انواع در Go
انواع سفارشی گروه بندی و شناسایی کدهای مشابه را برای استفاده مجدد آسان می کند.
کد اعلان انواع سفارشی:
type typeName dataType
هنگام ایجاد یک نوع سفارشی و اختصاص یک متغیر، می توانید نوع را با استفاده از ()refleft.TypeOf که یک متغیر را می گیرد و نوع متغیر را برمی گرداند بررسی کنید.
import( "fmt"
"reflect")
type two int // creates type "two"
var number two // variable of type "two"
fmt.Println(reflect.TypeOf(number))
را
متغیر عدد از نوع دو است که یک عدد صحیح است. می توانید برای ایجاد بیشتر نوع سفارشی بیشتر بروید.
ایجاد ساختارها در Go
Structs (ساختارها) نقشه هایی برای برنامه نویسی شی گرا در Go هستند. ساختارها مجموعهای از فیلدها هستند که توسط کاربر تعریف شدهاند.
یک ساختار میتواند شامل انواع مختلفی از دادهها، از جمله انواع و روشهای ترکیبی باشد.
شما می توانید با استفاده از این دستور یک ساختار ایجاد کنید:
type StructName struct {
// some code
}
به طور متعارف، نام سازه ها معمولاً برای خوانایی با حروف بزرگ و شتر نوشته می شوند.
نوع ساختار نام فیلدها و انواع داده ها را می گیرد. ساختارها می توانند در هر نوع داده Go، از جمله انواع سفارشی، استفاده کنند.
type User struct {
field1 string
field2 int
fieldMap map[string]int
}
شما می توانید با اختصاص دادن ساختار به عنوان یک متغیر، یک نوع ساختار را نمونه سازی کنید.
instance := User{
// some code
}
نمونه ساختار را می توان با فیلدهایی در نمونه سازی که در زمان اولیه تعریف شده است پر کرد یا روی null تنظیم کرد.
instance := User{
field1: "a string field",
field2: 10,
fieldMap: map[string]int{},
}
دسترسی به عناصر ساختاری
شما می توانید با استفاده از علامت نقطه در فیلد به فیلدهای یک نمونه ساختار دسترسی داشته باشید.
fmt.Println("Accessing a field of value", instance.field2)
این خروجی فیلد 2 نمونه ساختار نمونه سازی شده است.
اختصاص روش ها به سازه ها
توابع (روش ها) با تعیین نام گیرنده و نام ساختار قبل از نام تابع همانطور که در نحو زیر نشان داده شده است به انواع ساختار اختصاص داده می شوند.
func (receiver StructName) functionName() {
// some code
}
متد functionName فقط در نوع ساختار مشخص شده قابل استفاده است.
پیاده سازی وراثت در Go
وراثت توانایی اشیا و انواع برای دسترسی و استفاده از روش ها و ویژگی های اشیاء دیگر است. Go به عنوان یک ویژگی Inheritance ندارد، اما می توانید از ترکیب بندی ها استفاده کنید. در Go، ترکیب مستلزم ارجاع به یک روبنا (ساختاری که باید به ارث برده شود) در یک زیرساخت با ارائه نام ابرساخت به زیرساخت است.
با استفاده از مثال ساختار بالا:
type User struct {
field1 string
field2 int
fieldMap map[string]int
}
type User2 struct {
User
}
با انتقال نام ساختار کاربر به ساختار User2، ساختار User2 می تواند به تمام روش ها و ویژگی های ساختار کاربر در نمونه سازی دسترسی داشته باشد، به جز تکنیک های انتزاعی که استفاده می شود.
son := User2{
User{
field1: "baby",
field2: 0,
fieldMap: nil,
},
}
fmt.Println(son.field2)
متغیر son در بالا نمونه ای از ساختار User2 است. همانطور که در مثال مشاهده می شود، متغیر son می تواند به مقادیری از نوع User دسترسی داشته باشد و از آنها استفاده کند.
کپسوله کردن فیلدهای نوع در Go
کپسولهسازی، که به عنوان «پنهان کردن اطلاعات» نیز شناخته میشود، تکنیکی است که روشها و ویژگیهای یک شی را در واحدهایی برای محدود کردن استفاده و دسترسی به جز موارد مشخص (فعال کردن امتیازات خواندن/نوشتن) محدود میکند.
کپسوله سازی در Go با استفاده از شناسه های صادر شده و صادر نشده در بسته ها پیاده سازی می شود.
شناسه های صادر شده (خواندن و نوشتن)
شناسه های صادر شده از بسته های تعریف شده آنها و دسترسی به برنامه های دیگر صادر می شوند. با بزرگ کردن یک شناسه فیلد، فیلد fo صادر می شود.
type User struct {
Field1 string
Field2 int
FieldMap map[string]int
}
type User2 struct {
User
}
شناسه های صادر نشده (فقط خواندنی)
شناسه های صادر نشده از بسته تعریف شده صادر نمی شوند و به طور معمول با حروف کوچک هستند.
type User struct {
field1 string
field2 int
fieldMap map[string]int
}
type User2 struct {
User
}
مفهوم شناسه های صادر شده و صادر نشده در روش های یک شی نیز صدق می کند.
چند شکلی در Go
چند شکلی تکنیکی است که برای دادن اشکال مختلف به یک جسم برای انعطاف پذیری استفاده می شود.
Go چند شکلی را با استفاده از رابط ها پیاده سازی می کند. رابط ها انواع سفارشی هستند که برای تعریف امضاهای متد استفاده می شوند.
اعلان رابط ها
اعلام اینترفیس ها شبیه به اعلان ساختارها است. با این حال، رابط ها با استفاده از کلمه کلیدی رابط اعلام می شوند.
type InterfaceName interface{
//some methods
}
اعلان های واسط شامل روش هایی هستند که باید توسط انواع ساختار پیاده سازی شوند.
پیاده سازی رابط ها در سازه ها
انواعی که اینترفیس را پیاده سازی می کنند باید اعلام شوند و پس از آن روش های نوع رابط را پیاده سازی کنند.
// The Interface
type Color interface{
Paint() string
}
// Declaring the structs
type Green struct {
// some struct specific code
}
type Blue struct {
// some specific code
}
قطعه کد بالا دارای یک رابط رنگی است که با متد Paint اعلام شده است تا با انواع ساختار سبز و آبی پیاده سازی شود.
اینترفیس ها با تخصیص متدهایی برای ساخت انواع و سپس نامگذاری متد توسط متد واسط برای پیاده سازی پیاده سازی می شوند.
func (g Green) Paint() string {
return "painted green"
}
func (b Blue) Paint() string {
return "painted blue"
}
متد Paint توسط انواع سبز و آبی اجرا می شود که اکنون می توانند متد Paint را فراخوانی کرده و از آن استفاده کنند.
brush := Green{}
fmt.Println(brush.Paint())
“Pinted green” بر روی کنسول چاپ می شود و تأیید می کند که رابط با موفقیت پیاده سازی شده است.
چکیده فیلدها در Go
انتزاع فرآیند پنهان کردن روشها و ویژگیهای بیاهمیت یک نوع است که ایمن کردن بخشهایی از برنامه را از استفاده غیرعادی و ناخواسته آسانتر میکند.
Go انتزاعی را از همان ابتدا اجرا نمی کند. با این حال، شما می توانید راه ما را از طریق پیاده سازی انتزاع با استفاده از رابط ها انجام دهید.
// humans can run
type Human interface {
run() string
}
// Boy is a human with legs
type Boy struct {
Legs string
}
// a method on boy implements the run method of the Human interface
func (h Boy) run() string {
return h.Legs
}
کد بالا یک رابط Human با یک رابط اجرا ایجاد می کند که یک رشته را برمی گرداند. نوع Boy متد اجرای رابط Human را پیادهسازی میکند و رشتهای را در instantiation برمیگرداند.
یکی از راههای پیادهسازی انتزاع این است که ساختاری را به ارث میبریم که متدهای آن انتزاع شوند. بسیاری از روش های دیگر وجود دارد، اما این ساده ترین است.
type Person struct {
Name string
Age int
Status Human
}
func main() {
person1 := &Boy{Legs: "two legs"}
person2 := &Person{ // instance of a person
Name: "amina",
Age: 19,
Status: person1,
}
fmt.Println(person.Status.run())
}
ساختار Person رابط Human را به ارث می برد و می تواند با استفاده از متغیر Status که رابط را به ارث می برد، به تمام روش های آن دسترسی داشته باشد.
در نمونه سازی با مرجع (با استفاده از یک اشاره گر)، نمونه Person struct Person2 به نمونه ای از Boy struct Person1 اشاره می کند و به متدها دسترسی پیدا می کند.
به این ترتیب، می توانید روش های خاصی را برای پیاده سازی بر اساس نوع مشخص کنید.
OOP در مقابل برنامه نویسی کاربردی
برنامه نویسی شی گرا یک پارادایم مهم است زیرا به شما کنترل بیشتری بر برنامه شما می دهد و استفاده مجدد از کد را تشویق می کند به روشی که برنامه نویسی کاربردی این کار را نمی کند.
این برنامهنویسی کاربردی را انتخاب بدی نمیکند، زیرا برنامهنویسی کاربردی میتواند برای برخی موارد مفید و بهتر باشد.