ディップ Advent Calendar の17日目です:)
はじめに
どんな記事?
JavaエンジニアがRubyを書くようになり、
「これJavaの◯◯みたいなことだったのか!」と思ったことを共有する記事です。
今回はコーディング
について書きます…!
目次
クラス
インスタンス化
メソッド
インスタンス化(引数あり)
配列/リスト
Map/ハッシュ
知っておくと役立ったこと
おわりに
クラス
Java
// デフォルトパッケージ
public class Father {
}
Ruby
class Father
end
インスタンス化
Java
// デフォルトパッケージ
public class Main {
public static void main(String[] args) {
Father father = new Father();
}
}
Ruby
require './father.rb' # ./father.rbを読み込む。javaでいうimportに似ています。
father = Father.new
メソッド
Java
宣言
public class Father {
// staticなメソッド
public static void hello() {
System.out.println("Hello...");
}
// 非staticなメソッド(インスタンスメソッド)
public void tellTheTruth() {
System.out.println("I am your father.");
}
// 非staticなメソッド(インスタンスメソッド):引数あり
public void fuga(String words) {
System.out.println(words);
}
}
呼び出し
public class Main {
public static void main(String[] args) {
Father.hello(); // Hello...
Father father = new Father();
father.tellTheTruth(); // I am your father.
father.fuga("Nooo!!"); // Nooo!!
}
}
Ruby
宣言
class Father
# クラスメソッド
def self.hello
puts 'Hello...'
end
# インスタンスメソッド(引数なし)
# snake_case記法
def tell_the_truth
puts 'I am your father.'
end
# インスタンスメソッド(引数あり)
def fuga(words)
puts words
end
end
呼び出し
require './father.rb'
Father.hello # hoge
father = Father.new
father.tell_the_truth() # I am your father.
father.tell_the_truth # I am your father. ()は省略可能。メンバの呼び出しに見えますが、メソッドの呼び出しです。
father.fuga('nooooo!!') # nooooo!!
father.fuga 'nooooo!!' # nooooo!! ()は省略可能。よく使用されますが、メソッドの右辺などでは分かりづらくなるので避けた方が良いでしょう。
インスタンス化(引数あり)
前述のインスタンス化では引数なしのコンストラクタでしたが、今回は引数を持つコンストラクタでよりオブジェクト感を出していきます。
Java
public class Father {
private String name;
public Father(String name) {
this.name = name;
}
public void tellTheTruth() {
System.out.println("I am " + name + "...");
}
}
Ruby
class Father
attr_accessor :name
def initialize(name)
@name = name
end
def tell_the_truth
puts "I am #{name}..."
end
end
initialize
がいわゆるコンストラクタです。
また、@hoge
はインスタンス変数を表します。
Javaではよく、フィールド
とかメンバ変数
とか呼ばれるものですね。
文字列について
- 文字列はシングルクォーテーション
'
で囲みましょう。- ダブルクオーテーション
"
は式展開時に使用します。 - 文字列はStringクラスのインスタンスです。
- ダブルクオーテーション
attr_accessor / アクセサについて
attr_accessor
はアクセサ(いわゆるgetter/setter)を定義するものです。
実際は、以下のコードを記述しているのと同じです。
def name
@name
end
def name=(val)
@name = val
end
Javaの以下と同じです。
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
配列/リスト
Java
package com.company;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> words = Arrays.asList("pen", "pineapple", "apple", "pen");
// java5-7
for (String word : words) {
System.out.println(word);
}
// java8以降
words.forEach(System.out::println);
}
}
Ruby
words = ['pen', 'pineapple', 'apple', 'pen']
puts words[0] # pen
words.each do |word|
# 以下の処理をループ実行する。
# wordにはループされたオブジェクトが格納されている。
# よって、最初のループは'pen'がコンソールに表示される。
puts word
end
配列はArrayクラスで表現されます。
Array - Rubyリファレンス
配列の繰り返しは#each
がしばしば使用されます。
for文もありますが、まずは#each
を覚えておけば大概のループは大丈夫でしょう。
do
からend
で表されるブロック
については、以下の記事が非常にわかりやすいです。
[Ruby] ブロックやProcの使いどころを理解する
(混乱する可能性があるので、ストックして後で読む方が良いかもしれません。)
また、文字列の配列は以下の書き方で生成されることも頭の片隅に置いておくと、
他の人が書いたコードを読んでドキドキする可能性が低くなるでしょう。
# 文字列の配列を生成する
words = %w(pen pineapple apple pen)
このあたりは、Rubyで%記法(パーセント記法)を使うが非常に参考になります。
(ストック推奨)
Map/ハッシュ
Java
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("name", "ディップ");
map.put("service", "ナースではたらこ");
System.out.println(map.get("name")); // ディップ
System.out.println(map.get("service")); // ナースではたらこ
}
}
Ruby
Rubyにおけるハッシュはいくつか書き方が用意されています。
# 1 文字列をキーとする
dip = {'name' => 'ディップ', 'service' => 'ナースではたらこ'}
puts dip['name'] # ディップ
puts dip['service'] # ナースではたらこ
# 2 シンボルをキーとする。
dip = {name: 'ディップ', service: 'ナースではたらこ'}
puts dip[:name] # ディップ
puts dip[:service] # ナースではたらこ
書き方は上記だけではなく、また、バージョンによってもサポートが異なります。
以下の記事が非常にわかりやすいので目を通すと良いでしょう。
Rubyのhash宣言方法いろいろ
知っておくと役立ったこと
名前空間について(Foo::Bar.newについて)
以下の書き方を見て戸惑うことがあるかもしれません。
Foo::Bar.new
こちらは、実際には以下のクラスをインスタンス化している処理です。
module Foo
class Bar
end
end
moduleの役割の一つに名前空間の提供があります。(他にはメソッドの提供などの機能を持ちます。)
Javaでいうパッケージに近い概念ですね。
package foo;
public class Bar {
}
package hoge;
import foo.Bar;
public class Fuga {
Bar bar = new Bar();
}
上記と似ています。
NullPointerExceptionではなく、NoMethodErrorが発生する
Rubyのnil
はJavaでいうnull
に似ていますが、多少異なります。
nil は NilClass クラスの唯一のインスタンスです。 nil は false オブジェクトとともに偽を表し、 その他の全てのオブジェクトは真です。
class NilClass (Ruby 2.3.0)
よって、nilクラスに存在しないメソッドを呼び出した際は、
NullPointerException
というような例外ではなく、NoMethodError
という例外が発生します。
# 定義していないメソッドを呼び出す。
nil.special_method
# NilClassにはspecial_methodとうメソッドはないので、以下のエラーが出力される。
undefined method `special_method' for nil:NilClass (NoMethodError)
おわりに
Rubyは文法が美しい上、組み込みクラスが便利で、使えば使うほど手に馴染む言語だと個人的に思います。
Javaから入ると「型宣言がないと何か不安!!」みたいになるかもしれませんが、すぐに慣れると思います。(3日で慣れました。)
他言語を始めると元の言語への見方も変わるので、是非始めてみるのはいかがでしょうか。