2016-11-21 11 views
-2

を見つけることができない...インターフェイスメソッドは、スーパークラスからサブクラスにこのコードを考える

type BaseItf1 interface { 
    getName() string 
    clone() *BaseStruct 
} 

type BaseStruct struct { 
    BaseItf1 
} 

func (bs *BaseStruct) cloneAndGetName() string { 
    sc := bs.clone() 
    return sc.getName() 
} 

type SubClass struct { 
    BaseStruct 
} 

func (sc *SubClass) getName() string { 
    return "A" 
} 

func (sc *SubClass) clone() *SubClass { 
    return &SubClass{} 
} 

func main() { 
    sc := &SubClass{} 
    fmt.Printf("-> %s\n", sc.clone().getName()) 
    fmt.Printf("-> %s\n", sc.cloneAndGetName()) 
} 

私はこのエラーを取得していますなぜ私はかなり理解することはできません。

panic: runtime error: invalid memory address or nil pointer dereference 
[signal SIGSEGV: segmentation violation code=0xffffffff addr=0x0 pc=0x2004a] 

cloneへの電話はmainで完全に自然に動作します。

cloneAndGetNameでは、cloneメソッドを呼び出すことはできません。 bsは、メソッドのBaseItfインターフェースを持つBaseStructへのポインターに入力されます。具体的なscmainのインスタンスは、cloneAndGetNameが呼び出され、cloneメソッドの位置を知るように見えます。

私には何が欠けていますか?これについてもっと良い方法がありますか?実際のコードでは、共有コードからオブジェクトの新しいインスタンスを作成する方法が必要です。

+0

sc.clone 'の最初の呼び出しは、()'あなたが見ているエラーを与え、ないコール:インタフェースがnilであれば

あなたも、デフォルトの動作を定義することができます'cloneAndGetName'にあります。 mainは 'sc:=&SubClass {};で置き換えることができます。 sc.clone() 'を呼び出して確認します。 –

+0

それについてはわからない、ポール。私が 'fmt.Printf(" - >%s \ n "、sc.clone()。getName())'をコメントすると、エラーは継続します。 – object88

+0

どちらもエラーがありますが、最初に表示されるもの(メインの 'sc.clone()')が表示されているエラーを引き起こします。コメントアウトすると、他のコマンドと同じエラーが発生します。あなたの質問のテキストは、2番目のコード( 'cloneAndGetName'のコード)がエラーを引き起こし、' 'main'の' clone'への呼び出しが自然に完璧に機能すると信じていました。 –

答えて

2

bs.clone()は失敗します。 に定義されているclone()*BaseStructという変数から呼び出すことはできません。 Goに型を埋め込むことは、他の言語のサブクラス化と同じではありません。

+0

確かに。私はこの問題の例を数多く読みましたが、私は自分のコードでそれを見ることができませんでした。ありがとう! – object88

0

まず、インターフェイスに関数を実装する必要があります。

package main 

import (
    "fmt" 
) 

type BaseItf1 interface { 
    getName() string 
    clone() *BaseStruct 
} 

type BaseStruct struct { 
    BaseItf1 
} 

func (bs *BaseStruct) cloneAndGetName() string { 
    sc := bs.clone() 
    return sc.getName() 
} 

func (bs *BaseStruct) getName() string { 
    return "" 
} 

func (bs *BaseStruct) clone() *BaseStruct { 
    return nil 
} 

type SubClass struct { 
    BaseStruct 
} 

func (sc *SubClass) getName() string { 
    return "A" 
} 

func (sc *SubClass) clone() *SubClass { 
    return &SubClass{} 
} 

func main() { 
    sc := &SubClass{} 
    fmt.Printf("-> %s\n", sc.clone().getName()) 
    fmt.Printf("-> %s\n", sc.cloneAndGetName()) 
} 
+0

私の謝罪;上記の固定メソッドの宣言が正しくありませんでした。しかし、 'BaseStruct'でメソッドを実装すると、' SubClass'でオーバーライドが呼び出されないので、結果は期待通りです。 – object88

+0

BaseStructの実装を最初に追加してください。 – duguying

+0

と入力してください。 ' - > A' – duguying

0

あなたが構造を持っているし、あなたがそのインターフェイスのすべてのメソッドを実装する必要がインターフェイスを満足する場合、あなたが内部の他のインタフェースとのインタフェースを持っている場合、それは違う、それだけでフィールドを持つだ構造体のために、コードsc.BaseItf1にタイプと値があるので、.clone().cloneAndGetName()への呼び出しに失敗しています。ここでメソッドを実装し:bs.BaseItf1.clone()bs.BaseItf1nilですが呼び出そうとしているため

type BaseItf1 interface { 
    getName() string 
    clone() *BaseStruct 
} 

type BaseStruct struct { 
    BaseItf1 // shortcut to BaseItf1 BaseItf1 <fieldName> <Type> 
} 

func (bs *BaseStruct) clone() *BaseStruct { 
    return &BaseStruct{} 
} 

func (bs *BaseStruct) getName() string { 
    // 
    // maybe BaseStruct should have a field Name, not sure if you want to 
    // in that case we can do: 
    // 
    // return bs.Name 

    return "a BaseStruct has no name" 
} 

func (bs *BaseStruct) cloneAndGetName() string { 
    sc := bs.clone() 
    return sc.getName() 
} 

type SubClass struct { 
    BaseStruct 
} 

func (sc *SubClass) methodA() string { 
    return "A" 
} 

func (sc *SubClass) methodB() *SubClass { 
    return &SubClass{} 
} 

func main() { 
    sc := &SubClass{} 

    fmt.Printf("type: %T and value: %v \n\n", sc.BaseItf1, sc.BaseItf1) 

    fmt.Printf("-> %q\n", sc.clone().getName()) 
    fmt.Printf("-> %q\n", sc.cloneAndGetName()) 
} 

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

+0

最初にいくつかの不正なメソッド宣言がありました。上記を訂正しました。しかし、あなたの例に従えば、予期した/望ましいエラーは得られません。 'SubClass'のメソッドオーバーライドは呼び出されず、' BaseStruct'のメソッドだけが呼び出されます。 – object88

1

埋め込みをインターフェイスフルフィルメントと混同しています。現在の状態では、struct​​に構造体BaseStructが埋め込まれており、インタフェースBaseItf1が埋め込まれています。ただし、問題があります。​​は、cloneAndGetName()メソッドをオーバーライドしません。そのため、このメソッドは組み込みのstruct で呼び出されます。埋め込みメソッド呼び出しは、組み込み構造体を埋め込み構造体ではなく受信者として使用して呼び出されます。したがって、BaseStruct構造体は、構造体をラップする構造体のメソッドではなく、独自のメソッドにのみアクセスできます。これらのメソッド自体は組み込みのインタフェースの結果であるため、BaseStructは埋め込みインタフェースのメソッド(nil)を呼び出します。これは、もちろん、セグメンテーションを引き起こします。

この場合、いくつかの基本構造で標準的なメソッドを定義したいが、その動作をサブクラスで上書きできるように見える。この場合、BaseClass内インターフェイスフィールドに​​のインスタンスを配置:

sc := BaseStruct{&SubClass{}} 
fmt.Printf("-> %s\n", sc.clone().getName()) 
fmt.Printf("-> %s\n", sc.cloneAndGetName()) 

この例では、sc.closeAndGetName()BaseStructに呼び出されるが、clone()getName()呼び出しはsubstructに発生します。

type BaseItf1 interface { 
    getName() string 
    clone() *BaseStruct 
} 

type BaseStruct struct { 
    sub BaseItf1 
} 

func (bs *BaseStruct) cloneAndGetName() string { 
    sc := bs.clone() 
    return sc.getName() 
} 

func (bs *BaseStruct) getName() string { 
    if bs.sub != nil { 
    return bs.sub.getName() 
    } 
    // default behavior 
    return "<nil>" 
} 

func (bs *BaseStruct) clone() *BaseStruct { 
    if bs.sub != nil { 
    return bs.sub.clone() 
    } 
    // default behavior 
    return bs 
} 

type SubClass struct { 
    // Doesn't need to embed BaseStruct 
    // ... 
} 

func (sc *SubClass) getName() string { 
    return "A" 
} 

func (sc *SubClass) clone() *BaseStruct { 
    return &BaseStruct{&SubClass{}} 
} 

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

関連する問題