Go
オブジェクト指向プログラミング
サーチ…
備考
ためのインタフェースは、ポインタ受信機で実現することができません*User
ではないUser
構造
Goは、ユーザー定義型を構造体と型エイリアスの形式でサポートしています。構造体は複合型であり、構造体型を構成するデータの構成要素はフィールドと呼ばれます 。フィールドは型と名前が一意でなければなりません。
package main
type User struct {
ID uint64
FullName string
Email string
}
func main() {
user := User{
1,
"Zelalem Mekonen",
"[email protected]",
}
fmt.Println(user) // {1 Zelalem Mekonen [email protected]}
}
これはまた、構造体を定義するための正当な構文です
type User struct {
ID uint64
FullName, Email string
}
user := new(User)
user.ID = 1
user.FullName = "Zelalem Mekonen"
user.Email = "[email protected]"
埋め込み構造体
構造体もデータ型であるため、匿名型フィールドとして使用できます。構造体が異なるパッケージからのものであっても、外部構造体は埋め込み構造体のフィールドに直接アクセスできます。この動作は、実装の一部またはすべてを別の型または一連の型から派生させる方法を提供します。
package main
type Admin struct {
Username, Password string
}
type User struct {
ID uint64
FullName, Email string
Admin // embedded struct
}
func main() {
admin := Admin{
"zola",
"supersecretpassword",
}
user := User{
1,
"Zelalem Mekonen",
"[email protected]",
admin,
}
fmt.Println(admin) // {zola supersecretpassword}
fmt.Println(user) // {1 Zelalem Mekonen [email protected] {zola supersecretpassword}}
fmt.Println(user.Username) // zola
fmt.Println(user.Password) // supersecretpassword
}
メソッド
Goではメソッドが
受信機と呼ばれる特定の型の変数に作用する関数
受信者はstructs
だけでなくfunction
でも、 int
、 string
、 bool
などの組み込み型のエイリアス型はメソッドを持つことができますが、このルールの例外は、 interfaces
(後述)はメソッドを持てないということです。インタフェースは抽象定義であり、メソッドは実装であり、コンパイルエラーを生成しようとします。
structs
とmethods
を組み合わせることで、オブジェクト指向プログラミングでclass
一番近いclass
を取得できます。
Goのメソッドには次のシグネチャがあります
func (name receiverType) methodName(paramterList) (returnList) {}
package main
type Admin struct {
Username, Password string
}
func (admin Admin) Delete() {
fmt.Println("Admin Deleted")
}
type User struct {
ID uint64
FullName, Email string
Admin
}
func (user User) SendEmail(email string) {
fmt.Printf("Email sent to: %s\n", user.Email)
}
func main() {
admin := Admin{
"zola",
"supersecretpassword",
}
user := User{
1,
"Zelalem Mekonen",
"[email protected]",
admin,
}
user.SendEmail("Hello") // Email sent to: [email protected]
admin.Delete() // Admin Deleted
}
ポインタVs値レシーバ
インスタンスのコピーを作成しないため、メソッドのレシーバーは通常はパフォーマンスの理由のポインターになります。これは、値レシーバーの場合と同様に、レシーバータイプが構造体の場合に特に当てはまります。受信機タイプをポインタにする理由は、受信機が指し示すデータを変更できるためである。
受信機が含むデータの変更を避けるために値受信機が使用され、受信機が大きな構造体である場合、受信機受信機は性能ヒットを引き起こす可能性がある。
package main
type User struct {
ID uint64
FullName, Email string
}
// We do no require any special syntax to access field because receiver is a pointer
func (user *User) SendEmail(email string) {
fmt.Printf("Sent email to: %s\n", user.Email)
}
// ChangeMail will modify the users email because the receiver type is a ponter
func (user *User) ChangeEmail(email string) {
user.Email = email;
}
func main() {
user := User{
1,
"Zelalem Mekonen",
"[email protected]",
}
user.SendEmail("Hello") // Sent email to: [email protected]
user.ChangeEmail("[email protected]")
fmt.Println(user.Email) // [email protected]
}
インタフェースと多態性
インタフェースはオブジェクトの振る舞いを指定する方法を提供します。何かができる場合はここで使用できます。インタフェースは一連のメソッドを定義しますが、これらのメソッドは抽象的であるためコードを含んでおらず、実装はそのインタフェースのユーザに委ねられています。ほとんどのオブジェクト指向言語とは異なり、インタフェースはGoに変数を含むことができます。
多態性は、オブジェクト指向プログラミングの本質であり、同じインタフェースに従う限り、さまざまな種類のオブジェクトを一様に扱うことができます。 Goインタフェースは、この機能を非常に直接的かつ直観的な方法で提供します
package main
type Runner interface {
Run()
}
type Admin struct {
Username, Password string
}
func (admin Admin) Run() {
fmt.Println("Admin ==> Run()");
}
type User struct {
ID uint64
FullName, Email string
}
func (user User) Run() {
fmt.Println("User ==> Run()")
}
// RunnerExample takes any type that fullfils the Runner interface
func RunnerExample(r Runner) {
r.Run()
}
func main() {
admin := Admin{
"zola",
"supersecretpassword",
}
user := User{
1,
"Zelalem Mekonen",
"[email protected]",
}
RunnerExample(admin)
RunnerExample(user)
}