8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ジェネリクスとは

ジェネリクスとは、プログラミング言語において関数やメソッドの使用するデータ型を抽象化して、色々な型で処理を行えるようにする機能のことです。

ジェネリクスを使うのはどんなとき?

例えば引数の値を合計するという処理を書きたいとします。

しかし、静的型付け言語では一般的にはデータ型によって処理を分ける必要があります。

Int型(整数)を扱う場合に、抽象操作としてAddInt、string型(文字列)を扱う場合にはAddstringを準備する必要があります。

しかし、合計する処理は同じなので一つにして影響箇所を限定させつつ、処理を抽象化したいですよね。

それを解決するためにジェネリクスを使用します。

ジェネリクスで書くとどうなるのか

実際にジェネリクスで書いた場合をTypeScriptとGoでやってみようと思います。

TypeScriptの場合

ジェネリクスで書かない場合はこうなります。

typescript
function AddInt(a: number, b: number): number {
  return a + b;
}

function AddString(a:string , b: string): string {

  return a + b;
}

それをジェネリクスで書くとこうなります。

typescript
function Add<T extends number | string>(a: T, b: T): T {
  if (typeof a === "number" && typeof b === "number") {
    return (a + b) as T;
  }
  if (typeof a === "string" && typeof b === "string") {
    return (a + b) as T;
  }
  throw new Error("Invalid type")
 }

T extendsと書くことで指定した型に限定して扱うことができるようになります。
このTがジェネリクスとして機能し、Tを使うことで変数として型指定を行うことができます。

Goの場合

goの場合、ジェネリクスを使わなければこういうコードになります。

go
func AddInt(a: int, b: int ) int{
  return a+b
}

func AddString(a: string, b:string) string{
  return a+b
}

ジェネリクスで書くとこうなります。

go
func Add[T int | string](a: T,b :T) T {
	return a + b
}

[]でジェネリクスの定義をしており、Tをintもしくはstringであるように定義しています。

ジェネリクスで使われている~って何?

Goでのジェネリクスについて調べていると下のような書き方が出てきました。

go
func Add[T ~int | ~string](a, b T) T {
	return a + b
}

~とはunderlying Typeというものです。日本語で言うと基底型と呼ばれるものです。

~をつけると、指定した型をunderlying Typeにしてる型を使うことができます。

例えば下のような型も使えるようになります。

go
type MyInt int

type MyMyInt Myint

~intとしていたらそれをunderlying Typeとしている型を使うことが可能になります。
なので、MyIntはintをunderlying Typeにしているので使うことができますし、MyMyIntも辿るとintがunderlying Typeになっているので使うことができます。

go
func main() {
	var a MyMyInt = 1
	var b MyMyInt = 2
	fmt.Println(Add(a, b))
}

anyは使わない方がいい?

ジェネリクスで、型をanyとすることでどのような値でも引数や返り値として指定できるようになります。

typescript
function AddString(a:any , b: any): any {

  return a + b;
}
go
func Add[T any](a, b any) any {
	return a + b
}

しかし、これを使うと形チェックが行われず、ランタイムエラーを吐いてしまうため、静的型付けの良さを使うことができません。

可能な限り使わないようにしましょう。

まとめ

ジェネリクスは、型を柔軟に扱うことができ、メソッドの抽象化を行い再利用性をあげることができます。

便利なのでぜひ使ってみてください。

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
8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?