Open6

go言語のtype 〇〇 interface { ... } を頑張る

wawasawawawasawa

https://medium.com/since-i-want-to-start-blog-that-looks-like-men-do/初心者に送りたいinterfaceの使い方-golang-48eba361c3b4

interface … で、これ何に使うねん?って私は最初に思いました。ここまではTour of Goを読んでいたら理解できると思いますが、実際どんな場| 面で使うのか全くわからなかったです。まだざっくりとした理解ですが、interfaceを使っていいことは具体的な実装を気にすることなく1つのまとまった塊として定義できることで、他の関数から扱いやすくなるといったところでしょうか?抽象的なことをいってもわからないので、具体例をあげます。

wawasawawawasawa

https://dokupe.hatenablog.com/entry/20181208/1544246322

メリット2: 実装を隠蔽する
これまでのコードでは単一のパッケージで実装していたため、やろうと思えば特定の型に依存したコードが書けてしまいます(例えば whiteTaiyaki.Nakami = "クリーム" というような書き方)。これではコードが密結合になってしまい、単体テストが書きづらくなったり、実装の変更時に影響範囲の把握が困難になったりして後々非常に苦労することになってしまいます。
ところで、Golangではパッケージを境界として関数や構造体の公開・非公開を制御することができます(Golangの基本:頭文字が大文字であればパッケージ外へ公開、小文字であれば非公開)。これを利用しインターフェースの実装部分のみを外部公開することで中身の構造体や内部処理に使う関数を隠蔽し特定の型・パッケージに強く依存したコードを書けなくすることができます。

要は属性の直接参照、編集をできなくすることで、コードの途中での意図せぬ属性の参照や変更を防げる。
また、インターフェース越しでしか操作できないので、例えばNakamiという属性をAnkoに変えたとしても、GetNakami()をインターフェース越しに使ってるmain .goでコード修正をする必要がない。


まぁ、普通にrubyでコード書いてるときもよくやることで、使い手側に影響が起きないように引数の数メソッド名を固定して改修を進めるような場面を思い浮かべた。

# はじめはこういうクラス定義だったのが
class User
  def initialize(name)
    @name = name
  end

  def name_with_san
    return "#{@name}さん"
  end
end

--- 

# その後こういうクラス定義に変わったとしても、
class User
  def initialize(onamae)
    @onamae = "#{@onamae}さん"
  end

  def name_with_san
    return @onamae
  end
end

--- 

# 変更前のname_with_sanの使い方がこうなのに対して、
user = User.new("山田") # 変更前は内部的に `@name` を使ってる
p user.name_with_san # ⇒ 山田さん

# 変更後のname_with_sanの使い方も特に変える必要がない
user = User.new("山田") # 変更後は内部的に `@onamae` を使ってる
p user.name_with_san # ⇒ 山田さん