LoginSignup
13
2

More than 3 years have passed since last update.

【Week 11】class, ruby_sixth

Last updated at Posted at 2020-12-28

はじめに

マルチスケールシミュレーション特論の講義メモです.講義メモのインデックスはコチラ

今回の参考資料はチャート式ruby-VI(hello class)です.

チャート式 Ruby

参照記事はコチラ

class

今回は class について学んでいく.オブジェクト思考の考え方の肝となるポイントととして

  • capsulation(隠蔽)
  • inheritance(継承)
  • polymorphism(多形)

の 3 つが挙げられるが,method やclass は 1 つ目の隠蔽に属するらしい.

hello class

以前作成した hello.rb を用いて class について学ぶ.

def puts_hello name
  puts "Hello #{name}."
end

def gets_name
  name = ARGV[0] || 'world'
  return name
end

name = gets_name
puts_hello name

class を用いて main 関数自体を無くしてしまおうというのが魂胆である.

まずは Hello class を作成する.

class Hello
  def puts_hello name
    puts "Hello #{name}."
  end

  def gets_name
    name = ARGV[0] || 'world'
    return name
  end
end

Hello.new

Hello.new は instance といって,これだけでは何も起きない.

ここで instance を作成した際に実行される initialize というメソッドを用いることで hello.rb 同等のプログラムを実装する.

class Hello
  def initialize
    name = gets_name
    puts_hello name
  end

  def puts_hello name
    puts "Hello #{name}."
  end

  def gets_name
    name = ARGV[0] || 'world'
    return name
  end
end

Hello.new

少しずつスタイリッシュになってきた.ここで気になるのが initialize メソッドの変数 name .引数として渡すべきか,関数 puts_hello 内で呼ぶべきか.

ここで class 特有の instance 変数が活躍する. @name とすることでオブジェクトが存在する限り instance 内で共有できる変数として扱うことができる.(ニュアンスはグローバル変数みたいな感じ,ニュアンスね.)

instance 変数を用いるとこんな感じ.

class Hello
  def initialize
    @name = gets_name
    puts_hello
  end

  def puts_hello name
    puts "Hello #{@name}."
  end

  def gets_name
    name = ARGV[0] || 'world'
    return name
  end
end

Hello.new

実行してみると,

> ruby hello_class.rb
Hello world.
> ruby hello_class.rb Rudy
Hello Rudy.

class を用いて hello.rb 通りの出力が得られるプログラムを作成できた.

method と object 指向

method と object 指向の違いについてこれまで意識したことがなかったので,これを機に学んでいく.

  • method: verb(subject, object)

  • object 指向: subject.verb(object)

確かに object 指向って後者のイメージ.

method 的なイメージは 関数名(必要とする変数) のような感じだけど,object 指向では 対象の変数.関数名(必要なもの) のようなイメージ.object 指向のほうがどの変数に対して働きかけているのかが理解しやすいのはこういうイメージからなのか.

とりあえず,講義資料どおり method ・ class の継承 ・ オーバーライドの書き方 3 通りを見てみる.

require 'colorize'

# method
def hello(name)
  "Hello #{name}."
end

# inherited class
class Greeter < String
  def hello
    "Hello #{self}."
  end
end

# extend class
class String
  def hello
    "Hello #{self}."
  end
end

# method call
name = ARGV[0]
puts hello(name).green

# inherited class call
greeter = Greeter.new(ARGV[0])
puts greeter.hello.green

# extend class call, override
puts ARGV[0].hello.green

method や class の部分を比較するのもよいが,注目するポイントは呼び出し部分.method の手法はいつも通り変数に代入して,引数に受けわたしている.

class の継承ではどうだろうか.一度 instance を作成し,その時に値を保持している.美しい.

override ではそもそも instance すら作成されていない.そもそも String class の中に処理を置いてしまうという図々しさ.ある意味スタイリッシュ.

どれが良いかと言ったら間違いなく override でしょ.それは人の好みによるか.

attr_accessor

参照記事を読んでみたものの,イマイチよくわからなかった.

実力不足.不甲斐なし.

発展問題

assert_equalをclass化して,Integerに override しなさい.

- 3.assert_equal 3でtrueが返るようになります.
- selfで3とかが返るはず.
- moduleをincludeする方が筋が良さそうですが...自信ありません.

とのこと,面白そうなのでやってみた.

require 'colorize'

class Integer
  def puts_vals(expected, result)
    puts "expected :: #{expected}"
    puts "result   :: #{result}"
  end

  def assert_equal(expected)
    puts_vals(expected, self)
    print  case expected == self
       when true  ; "succeeded in #{__method__}.\n".green
       when false ; "failed in #{__method__}.\n".red
    end
  end
end

puts 3.assert_equal 3
> ruby assert_equal_class.rb
expected :: 3
result   :: 3
succeeded in assert_equal.

できたっぽいね.今回でオブジェクト指向の良さが少しわかった気がする.

Ruby 開発周辺情報

今回はチャート式 Ruby のみです.

次回の講義内容 <2020-12-16 Wed>

次回の講義は

だそうです.


  • source ~/grad_members_20f/members/e79a93e5b7b1/posts/class/c11_20201202.org
13
2
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
13
2