はじめに
マルチスケールシミュレーション特論の講義メモです.講義メモのインデックスはコチラ
今回の参考資料はチャート式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