Help us understand the problem. What is going on with this article?

go言語でオブジェクト指向っぽく書いてみた

More than 1 year has passed since last update.

はじめに

この記事は,SLP KBIT Advent Calendar 2018 の12日目の記事です.

先日,クラスについて学習する機会がありました.クラスのほんの一部しか触っていませんが,とても便利なものだと気づかされたので,Go言語でも実践したいと思いました.しかし,Go言語にはそもそもクラスというものが存在しません.そこで,実際に作ってみることにしました.クラスやオブジェクト指向について完璧に理解できたかと言われたらそうではないので,間違い等あればご指摘ください.

Go言語を使う理由は,特にありません.ただ使いたかっただけです.

開発環境

OS: Windows 10
言語: go 1.11

クラスとは

構造体に手足が生えて己の意思で動けるようになったものです.(#あくまでイメージ)

作ったもの

何かを作りながらやりたいので,簡単なゲームを作りながらやってみます.作るものはじゃんけんです.自分がじゃんけんをするのはめんどくさいので,じゃんけんをするユニットを2つ作ります.10回勝負して,勝った回数を表示するようなゲームを作ろうと思います.0をグー,1をチョキ,2をパーとして作っていきます.

構造体の定義

unit
type unit struct {
    name     string
    stone    int
    scissors int
    paper    int
    janken   int
    winCount int
}

ユニットの構造体を定義します.プロパティとしては,ユニットの名前と,グーとチョキとパーをどの割合で出すかのパラメータと,現在出している手と,勝った回数を用意しておきます.

初期化時に必要なメソッド

newUnit
func (unit *unit) newUnit(name string, stone, scissors, paper int) {
    unit.name = name
    unit.stone = stone
    unit.scissors = scissors
    unit.paper = paper
    unit.janken = -1
    unit.winCount = 0
}

newUnitは,Javaでいうコンストラクタです.新しいユニットを作るときに使います.

その他のメソッド群

choiseJanken
func (unit *unit) choiseJanken() {
    time.Sleep(1 * time.Nanosecond)
    rand.Seed(time.Now().UnixNano())
    randomNumber := rand.Intn(unit.stone + unit.scissors + unit.paper)
    switch {
    case randomNumber < unit.stone:
        unit.janken = 0
    case randomNumber < unit.stone+unit.scissors:
        unit.janken = 1
    default:
        unit.janken = 2
    }
}

choiseJankenは,グーとチョキとパーをどの割合で出すかによって手を変えるようにしました.こうすることで,ユニット毎に違った個体を作ることができます.乱数を生成する前に1ナノ秒スリープしているのは,短期間で複数の乱数を生成すると同じ値になってしまうからです.少し時間をずらすことによって乱数が正しく生成されるようになりました.

incrementWinCount
func (unit *unit) incrementWinCount() {
    unit.winCount++
}

getName
func (unit unit) getName() string {
    return unit.name
}
getWinCount
func (unit unit) getWinCount() int {
    return unit.winCount
}
getJanken
func (unit unit) getJanken() int {
    return unit.janken
}
getJankenString
func (unit unit) getJankenString() string {
    switch unit.getJanken() {
    case 0:
        return "グー"
    case 1:
        return "チョキ"
    }
    return "パー"
}

incrementWinCountは勝利をしたときにカウントするメソッド,getNameはunitの名前を返却するメソッド,getWinCountは勝利数を返却するメソッド,getJankenはじゃんけんで出した手の数字を返却するメソッド,getJnakenStringはじゃんけんで出した手の数字に対応する文字列を返却するメソッドです.ここで注意したいのは,getがついているメソッドには,レシーバとしてunit型の変数を値渡しで渡しているのに対して,getがついていないメソッドは参照渡しで渡されているということです.つまり,メソッドによって値を書き換える権利があるものとないものに分けられているということを表しています.これは,プライベートとパブリックに近づけたかったからです.

main関数

main
func main() {

    var unit1, unit2 unit
    unit1.newUnit("taro", 5, 3, 1)
    unit2.newUnit("jiro", 1, 1, 2)

    for i := 0; i < 10; i++ {
        unit1.choiseJanken()
        unit2.choiseJanken()
        fmt.Println(unit1.getName(), ": ", unit1.getJankenString())
        fmt.Println(unit2.getName(), ": ", unit2.getJankenString())
        switch unit1.getJanken() {
        case unit2.getJanken():
            fmt.Println("Draw")
        case (unit2.getJanken() + 1) % 3:
            fmt.Println("Winner: ", unit2.getName())
            unit2.incrementWinCount()
        default:
            fmt.Println("Winner: ", unit1.getName())
            unit1.incrementWinCount()
        }
        fmt.Println()
    }

    fmt.Println("result")
    fmt.Println(unit1.getName(), ": ", unit1.getWinCount())
    fmt.Println(unit2.getName(), ": ", unit2.getWinCount())

}

感想

コードを見てもクラスで固まっているわけではないので,クラスっぽくはないのですが,動きとしては,クラスに寄せることができたかなと思います.(クラスごとにフォルダを分ければもっとそれっぽくなりそう)
オブジェクトの視点でコードを書いていくの楽しい!!と思いました.

参考

http://www.geocities.jp/m_hiroi/golang/index.html

hirany
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした