0
0

入門者のためのinterface

Posted at

interfaceが何か分からなかったので勉強してみた。入門者にわかるように説明してみる。

まずは、chatGPTに解説してもらう。


Q:interfaceってなに?

インターフェース(Interface)は、プログラミング言語において、メソッドの集合を定義する抽象的な型です。具体的な実装を持たず、メソッドのシグネチャ(メソッド名、引数、戻り値の型)のみを指定します。

インターフェースは以下のような特徴を持ちます:

メソッドの集合: インターフェースは1つ以上のメソッドの集合を定義します。これらのメソッドはシグネチャのみを持ち、具体的な実装は持ちません。

ポリモーフィズムの実現: インターフェースは、異なる型のオブジェクトを同じインターフェース型として扱うことができるポリモーフィズムの実現に役立ちます。つまり、同じインターフェースを実装する複数の型は、互換性があり、同じメソッドを呼び出すことができます。

データの抽象化: インターフェースはデータの抽象化に役立ちます。インターフェースを使用することで、特定のメソッドを持つオブジェクトを必要とする部分に対して、具体的な型に依存せずに汎用的なインターフェースを使用することができます。

インターフェースは、プログラムの柔軟性、再利用性、テスト容易性を向上させるために使用されます。コードの組織化や拡張性の向上にも貢献します。

注意点として、Go言語ではインターフェースの実装は明示的に宣言する必要があります。つまり、インターフェースを満たすために必要なメソッドを実装する必要があります。


ありがとうchatGPT。でも、まだ分からないよ。
ここまでのinterfaceの理解をまとめてみる。

  • interfaceとは、go言語で扱う概念のこと。
  • interfaceとはメソッドの集合のこと。
  • interfaceを利用するとポリモーフィズムの役立つ。
  • interfaceはデータの抽象化に役立つ。
  • interfaceはプログラムを柔軟にして再利用やテスト用意生を向上させる
  • go言語では明示的に宣言する必要がある。

なんとなーくわかったような、、、気がしてしまうが何もわかっていない。
一旦簡単なコードで実装して理解を深めようと試みてみる。
頼むぜchatGPT

Q:簡単なコードで実装して説明して

もちろんです!以下にGo言語でのインターフェースの簡単な実装例を示します。

package main

import "fmt"

// Shape インターフェース
type Shape interface {
	Area() float64
}

// Circle 構造体
type Circle struct {
	Radius float64
}

// Area メソッドの実装
func (c Circle) Area() float64 {
	return 3.14 * c.Radius * c.Radius
}

// Rectangle 構造体
type Rectangle struct {
	Width  float64
	Height float64
}

// Area メソッドの実装
func (r Rectangle) Area() float64 {
	return r.Width * r.Height
}

func main() {
	circle := Circle{Radius: 5.0}
	rectangle := Rectangle{Width: 4.0, Height: 3.0}

	shapes := []Shape{circle, rectangle}

	for _, shape := range shapes {
		fmt.Println("面積:", shape.Area())
	}
}

このコードでは、Shapeという名前のインターフェースを定義しています。Shapeインターフェースには、Areaというメソッドが含まれています。このメソッドはfloat64型の面積を返します。

次に、Circleという構造体を定義し、Areaメソッドを実装します。同様に、Rectangleという構造体も定義し、Areaメソッドを実装します。

main関数では、circleとrectangleのインスタンスを作成し、それぞれの面積を計算して表示します。shapesというShapeのスライスにそれらのインスタンスを格納し、ループを使用してそれぞれの面積を取得して表示します。

このコードを実行すると、以下の出力が得られます。。

面積: 78.5
面積: 12

この例では、CircleとRectangleの両方がShapeインターフェースを実装しており、Shape型のスライスに両方の型の値を格納することができます。インターフェースを使用することで、異なる型のオブジェクトを統一的に扱うことができます。


さっきchatGPTが説明してくれた内容を踏まえてコードをよく見てみる。

  • interfaceとはメソッドの集合のこと。
type Shape interface {
	Area() float64
}

shapeというinterfaceが宣言されていて、中には関数と戻り値が記載されている。

type Circle struct {
	Radius float64
}

これは構造体。構造体には色々なデータ型を持たせることができる。
例えば、今回のようなfloat64型のRadiuいsというフィールド。
他にも、配列や構造体、インターフェースも持たせることができる。ちょっと大きなマルチケースみたいなものだろうか。

func (c Circle) Area() float64 {
	return 3.14 * c.Radius * c.Radius
}

これは先ほどの構造体が持っている関数を示しているらしい。構造体関数っていうらしい。
つまり、構造体 CircleはArea()という関数をもっていているらしい。関数の意味はおそらく円の面積を求めてfloat64型として呼び出し元(レシーバー)へ返すらしい。

type Rectangle struct {
	Width  float64
	Height float64
}

これも構造体、長方形のこと。フィールドにはfloat64型のWidthとHeightを持っている。

func (r Rectangle) Area() float64 {
	return r.Width * r.Height
}

これは先ほどと似ているが少し違う。具体的にはメソッドが属している構造体が違う。同じ関数名でも、属している構造体が違えば違う関数、メソッドとなる。っぽい。

func main() {
	circle := Circle{Radius: 5.0}
	rectangle := Rectangle{Width: 4.0, Height: 3.0}

	shapes := []Shape{circle, rectangle}

	for _, shape := range shapes {
		fmt.Println("面積:", shape.Area())
	}

これはmain関数という特別な関数。go言語は必ずこのmain関数から実行されるらしい(エントリーポイント)。
中身を見てみる。
構造体circleのフィールドに値を代入したものを変数circleに代入している(インスタンス)。
同じようにrectangleにも行っている。

現状を整理すると
インスタンスcircleはRadius: 5.0という値とメソッドArea()を持っている
インスタンスrectangleはWidth: 4.0, Height: 3.0という値とメソッドArea()を持っている

そして、そのインスタンスをShapeというスライスに格納する。
Shape = [circleはRadius: 5.0という値とメソッドArea()を持っている, rectangleはWidth: 4.0, Height: 3.0という値とメソッドArea()を持っている]

これをshapeという変数に格納する。

shape = [circleはRadius: 5.0とメソッドArea(), rectangleはWidth: 4.0, Height: 3.0とメソッドArea()]

for _, shape := range shapes {
		fmt.Println("面積:", shape.Area())
	}

これはスライスに格納されている要素を一つずつ取り出して処理を実行するループ構文for_rangeらしい。

fmt.Println("面積:", shape.Area())

これはループ処理で実行されている処理内容。
面積というテキストとshapeが持っているArea()メソッドの実行結果が出力されている。

今更ながら構造体関数について補足すると、構造体関数を実行できるレシーバーはメソッドが属している構造体のみ。
今までの構造体関数を見てみると
circleのメソッドArea()
rectanglのメソッドArea()

なので、本来であれば、Area()というメソッドは各構造体にしか呼び出せないメソッドのはず。
それを呼び出せるように実現したのがinterface!

もう一度chatGPTの解説を見てみると、
CircleとRectangleの両方がShapeインターフェースを実装しており、Shape型のスライスに両方の型の値を格納することができます。インターフェースを使用することで、異なる型のオブジェクトを統一的に扱うことができます。

各構造体がinterfaceを持つことで、違う型のものを統一的に扱うことができたと書いてある。

つまり、

//このinterfaceを
type Shape interface{
    Area() floar64
}

//circleは持っている
func (c Circle) Area() float64 {
	return 3.14 * c.Radius * c.Radius
}

//rectangleも持っている
func (r Rectangle) Area() float64 {
	return r.Width * r.Height
}

//同時に実行できる!
fmt.Println("面積:", shape.Area())

これでやっとinterfaceのメリットや使い方がわかったような気がする。
もし、interfaceがない場合のコードをみて、その便利さを確認する。

package main

import "fmt"

type Circle struct {
	Radius float64
}

type Rectangle struct {
	Width  float64
	Height float64
}

func (c Circle) Area() float64 {
	return 3.14 * c.Radius * c.Radius
}

func (r Rectangle) Area() float64 {
	return r.Width * r.Height
}

func main() {
	circle := Circle{Radius: 5.0}
	rectangle := Rectangle{Width: 4.0, Height: 3.0}

	circleArea := circle.Area()
	rectangleArea := rectangle.Area()

	fmt.Println("円の面積:", circleArea)
	fmt.Println("長方形の面積:", rectangleArea)
}

構造体関数を実行できるのは、メソッドが属している関数だけなので、コードが冗長化していますね。。
interfaceに対してなんとなくイメージが持てたので一旦休憩にしましょう!

ちなみに、以下がchatGPTに作ってもらった記事です。

入門者にわかるように説明!Go言語のインターフェース(Interface)とは?

こんにちは、みなさん!Go言語の入門者向けに、インターフェース(Interface)について説明します。インターフェースはGo言語の重要な概念の一つで、柔軟性や再利用性の向上に役立ちます。初めて聞く方も安心してください。わかりやすく解説していきます!

インターフェースとは?

インターフェースは、プログラミング言語において、メソッドの集合を定義する抽象的な型です。具体的な実装を持たず、メソッドのシグネチャ(メソッド名、引数、戻り値の型)のみを指定します。

インターフェースの特徴は以下の通りです。

  • メソッドの集合:インターフェースは1つ以上のメソッドの集合を定義します。これらのメソッドはシグネチャのみを持ち、具体的な実装は持ちません。
  • ポリモーフィズムの実現:インターフェースを使用することで、異なる型のオブジェクトを同じインターフェース型として扱うことができます。つまり、同じインターフェースを実装する複数の型は、互換性があり、同じメソッドを呼び出すことができます。
  • データの抽象化:インターフェースを使用することで、特定のメソッドを持つオブジェクトを必要とする部分に対して、具体的な型に依存せずに汎用的なインターフェースを使用することができます。
    インターフェースはプログラムの柔軟性、再利用性、テスト容易性を向上させるために使用されます。また、コードの組織化や拡張性の向上にも貢献します。

ただし、Go言語ではインターフェースの実装は明示的に宣言する必要があります。つまり、インターフェースを満たすために必要なメソッドを実装する必要があります。

サンプルコードでインターフェースを理解しよう!

では、実際のコードを通じてインターフェースを理解していきましょう。以下のコードは、円と長方形の面積を計算するプログラムです。

Copy code
// Shape インターフェース
type Shape interface {
	Area() float64
}

// Circle 構造体
type Circle struct {
	Radius float64
}

// Area メソッドの実装
func (c Circle) Area() float64 {
	return 3.14 * c.Radius * c.Radius
}

// Rectangle 構造体
type Rectangle struct {
	Width  float64
	Height float64
}

// Area メソッドの実装
func (r Rectangle) Area() float64 {
	return r.Width * r.Height
}

func main() {
	circle := Circle{Radius: 5.0}
	rectangle := Rectangle{Width: 4.0, Height: 3.0}

	shapes := []Shape{circle, rectangle}

	for _, shape := range shapes {
		fmt.Println("面積:", shape.Area())
	}
}

このコードでは、Shapeという名前のインターフェースを定義しています。Shapeインターフェースには、Areaというメソッドが含まれています。このメソッドはfloat64型の面積を返します。

次に、Circleという構造体を定義し、Areaメソッドを実装します。同様に、Rectangleという構造体も定義し、Areaメソッドを実装します。

main関数では、circleとrectangleのインスタンスを作成し、それぞれの面積を計算して表示します。shapesというShapeのスライスにそれらのインスタンスを格納し、ループを使用してそれぞれの面積を取得して表示します。

このコードを実行すると、以下の出力が得られます。

makefile
Copy code
面積: 78.5
面積: 12
この例では、CircleとRectangleの両方がShapeインターフェースを実装しており、Shape型のスライスに両方の型の値を格納することができます。インターフェースを使用することで、異なる型のオブジェクトを統一的に扱うことができます。

インターフェースの活用により、コードの柔軟性や再利用性が高まり、テスト容易性も向上します。ぜひインターフェースを使って、より効果的なプログラミングを実現してみてください!

以上が、Go言語のインターフェースについての入門解説でした。理解に役立つと嬉しいです!もし質問や疑問点があれば、お気軽にコメントしてください。みなさんの学びの手助けになるよう、サポートします。Happy coding!✨

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0