RubyAdventCalendar2016 12/15の記事です。
最初に
PHPを今まで長い間書いてきて、そろそろRubyを勉強しようと思っている人向けです。
PHPではこうだけどRubyの場合はこう。という流れで基本的には進めていきます。
私自身も勉強を始めてまだ日が浅いので、ツッコミあったらどんどんください。
本記事はRubyを網羅する事を目的にはしていません。
versionについて
実行しているバージョンは以下の通りです。
☁ ~ php -v
PHP 7.1.0 (cli) (built: Dec 14 2016 00:12:28) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.1.0-dev, Copyright (c) 1998-2016 Zend Technologies
☁ ~ ruby -v
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]
☁ ~
IDEについて
IDEよりエディタ派だ!男は黙ってVim!という方は読み飛ばしてください。
お勧めIDE
Rubymine
PHPの場合はPhpStormが有名ですが、Rubyの場合はRubyMineを強くお勧めします。
※私はPhpStormを愛しています。
PhpStormと同じJetBrains製なので、もしPhpStormを普段よく使っているなら学習コストほぼ0でRubyMineも利用できます。
シンタックスもサジェストしてくれたり、コード補完もすごく優秀なのでRubyの学習効率もかなり上がります。
ただし、一点注意があります。PhpStormでは、基本全ての変数や関数が補完できます(PHPDocちゃんと書いていれば)。これがPhpStormが手放せない理由の一つです。これはPHPが静的解析に向いているからです。Rubyの場合は、動的な関数の定義が可能なのでそこまで解析する事は難しいと想像します。なのでRubyの場合は補完できないケースがままあります。例えばgemでとってきたライブラリの一部など。それでも私はRubyMineを推します。ちなみにRailsの場合はバンドルされている超優秀なプラグインがあるので、めちゃくちゃ快適です。
30日無料トライアル可能なのでまずはRubyMineを触ってみてください。きっと虜になるはずです。
RubyMineの魅力を存分に語ってくれている記事を貼っておきます。
メインの開発ツールをVimからRubyMineに変更した理由
nullについて
PHPではnull
ですが、Rubyではnil
です。
Rubyは全てがオブジェクト
Rubyは全てがオブジェクトです。ここがPHPと大きく違うところですね。
全てがオブジェクトだからこそエレガントに書くことが出来ます。
文字列もオブジェクトです。
p 'abc'.length
# 結果
3
そう、nilもね。
p nil.nil?
# 結果
true
関数について
<?php
function calc($a, $b)
{
echo $a + $b . PHP_EOL;
}
calc(1, 2);
# 結果
3
# 関数の定義
def calc(a, b)
p a+b
end
calc(1, 2)
# 関数呼び出し時の括弧は省略可能
calc 1, 2
# 結果
3
3
返り値
<?php
function calc($a, $b)
{
return $a + $b;
}
$total = calc(1, 2);
echo $total . PHP_EOL;
# 結果
3
def calc(a, b)
return a+b
end
total = calc(1,2)
p total
# 結果
3
returnを省略できる。
def calc(a, b)
a+b #最後の行の結果が返る
end
total = calc(1, 2)
p total
# 結果
3
classについて
基本
class Hoge
# メンバ関数の定義
def fuga
p 'this is fuga!'
end
end
## 継承
class HogeHoge < Hoge
end
a = Hoge.new
a.fuga
b = HogeHoge.new
b.fuga
# 結果
"this is fuga!"
"this is fuga!"
初期化
<?php
class Hoge
{
function __construct()
{
echo 'initial var' . PHP_EOL;
}
}
$a = new Hoge;
# 結果
'init var'
class Hoge
def initialize
p 'initial var'
end
end
a = Hoge.new
# 結果
"initial var"
クラスメソッド
<?php
class Hoge{
static function fuga(){
echo 'this is static function!'.PHP_EOL;
}
}
Hoge::fuga();
# 結果
'this is static function!'
class Hoge
def self.fuga
p 'this is static method!'
end
end
Hoge::fuga
# 結果
"this is static method!"
メソッドのアクセス権設定
PHPの場合は各メソッド毎にアクセス修飾子にてアクセス権を設定します。
<?php
class Hoge
{
public function publicFunc()
{
echo 'this is public method!' . PHP_EOL;
}
private function privateFunc()
{
echo 'this is private method!' . PHP_EOL;
}
}
$a = new Hoge();
$a->publicFunc();
$a->privateFunc();
# 結果
this is public method!
Fatal error: Call to private method hoge::privateFunc() from context '' in ...
Rubyの場合はまとめて指定します。これに関してはエレガントなのかわかりません。。
class Hoge
public #publicの場合は省略可能
def public_func1
p 'this is public method1'
end
def public_func2
p 'this is public method2'
end
private
def private_func1
p 'this is private method1'
end
def private_func2
p 'this is private method2'
end
end
a=Hoge.new
a.public_func1
a.public_func2
a.private_func1
a.private_func2
# 結果
"this is public method1"
"this is public method2"
access.rb:21:in `<main>': private method `private_func1' called for #<Hoge:0x007fa18b1291f0> (NoMethodError)
setter/getter
<?php
class Hoge
{
private $var;
function __construct()
{
$this->var = 'initial var';
}
function setVar($txt)
{
$this->var = $txt;
}
function getVar()
{
return $this->var;
}
}
$a = new Hoge;
echo $a->getVar().PHP_EOL;
$a->setVar('hogehoge');
echo $a->getVar().PHP_EOL;
# 結果
initial var
hogehoge
rubyの場合はプロパティの宣言が不要です。
initializeで初期化してますが、これも必須ではありません。
class Hoge
def initialize
@var ='initial var' #インスタンス変数(省略可能)
end
def set_var(txt)
@var = txt
end
def get_var
@var
end
end
a = Hoge.new
p a.get_var
a.set_var 'hogehoge'
p a.get_var
# 結果
"initial var"
"hogehoge"
Rubyの場合は別の書き方が出来ます。
class Hoge
attr_accessor :var #varのsetter/getterのセット
def initialize
@var ='initial var'
end
end
a = Hoge.new
p a.var
a.var = 'hogehoge'
p a.var
# 結果
"initial var"
"hogehoge"
ただし、これだとPHPのpublicな変数と一緒になってしまうので使いすぎに注意です。
実際には読み取り専用にするシチュエーションが多いと思うので、その場合は以下のようにします。
class Hoge
attr_reader :var #varのgetterのみ
def initialize
@var ='initial var'
end
end
a = Hoge.new
p a.var
a.var = 'hogehoge'
p a.var
# 結果
"initial var"
for.rb:11:in `<main>': undefined method `var=' for #<Hoge:0x007f8844805d08 @var="initial var"> (NoMethodError)
Did you mean? var
あと、替わりにattr_writer
を使うと書き込み専用となります。
その他シンタックス
条件分岐
if
<?php
$a = 'hoge';
if ($a === 'hoge') {
echo 'true' . PHP_EOL;
} else {
echo 'false' . PHP_EOL;
}
a = 'hoge'
if a == 'hoge'
p 'true'
else
p 'false'
end
ほぼ一緒ですね。違うのは、rubyでは===
じゃなくて==
を使う事。
===
もシンタックス的にはokだけど、「特殊な等号演算子」で主にcase文の比較で用いられる。
詳しくは、当記事のコメント参照。
ワンライナーだと、
<?php
$a = 'hoge';
if ($a === 'hoge') echo 'true' . PHP_EOL;
a = 'hoge'
p 'true' if a == 'hoge'
rubyだと後置ifになります。
否定
<?php
$a = 'hoge';
if ($a !== 'hoge') {
echo 'true' . PHP_EOL;
} else {
echo 'false' . PHP_EOL;
}
a = 'hoge'
unless a == 'hoge'
p 'true'
else
p 'false'
end
rubyでは否定を先に評価する場合は、unlessを使うと表現力が上がります。unlessの場合にelseを使う場合は二重否定になって読みにくいので推奨はされていません。
for
<?php
for ($num = 0; $num < 10; $num++) {
echo $num . PHP_EOL;
}
これがrubyだと、
for num in 0...10 do
p num
end
また、次のようにも書けます。
(0...10).each do |num|
p num
end
そして一番直感的なのは、以下の記述でしょう。
10.times.each do |num|
p num
end
foreach
配列
<?php
$array = ['a','b','c'];
foreach($array as $v){
echo $v.PHP_EOL;
}
# 結果
"a"
"b"
"c"
array = ["a","b","c"]
array.each do |v|
p v
end
# 結果
"a"
"b"
"c"
ハッシュ
<?php
$hash = ['one'=>'a','two'=>'b','three'=>'c'];
foreach($hash as $k=>$v){
echo "{$k}:{$v}".PHP_EOL;
}
# 結果
"one:a"
"tow:b"
"three:c"
hash = {one:"a",tow:"b",three:"c"}
hash.each do |k,v|
p "#{k}:#{v}"
end
# 結果
"one:a"
"tow:b"
"three:c"
おわりに
他にもブロック付き引数とか覚える事はいっぱいあるんですが、PHPが書ければとりあえずRubyもすんなり書けるよ!という事で、Ruby参入の障壁はほとんど無い事が理解してもらえたら嬉しいです。
あとは私もですがRailsのコードリーディングをやってみたりして、わからない記述があったら少し深く調べてみたりと、少しづつキャッチアップしていけたらよいかなと思います。