LoginSignup
0
0

More than 3 years have passed since last update.

Javaエンジニアが今さらRubyの基礎文法を覚えるために対比した その2(クラス、メソッド編)

Posted at

はじめに

2回目はクラスとかメソッドです。

環境

paiza.ioでこういう時は実行すると楽です

これを作った時のバージョンは以下です。バージョンはヘルプから確認できます。

Ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]
Java openjdk version "12" 2019-03-19

スコープの話

JavaもRubyもpublic,protected,privateが存在していますが、概念が違うので、項を分けました。

publicは同じで制限無しなのですが、protectedとprivateは違います。

詳しくはこちらを参考にさせていただきつつJavaエンジニア的な解釈で書いています。

なお、package privateの概念はRubyにはないようです。

クラススコープ

public(記述しない)とprivateが存在します。
インナークラスじゃないクラスをprivateにして使うみたいなシチュエーションはWebやってると使う機会がなさそうなので(今のところの感想)、見なかったことにします。
必要に応じてどういうスコープになるのか追加で学習します。

Javaでインナークラスも最近使ってないなーって感じなので、今回の記事ではスコープまでは扱いません。ご了承ください。

メソッドスコープ

public(記述しない)、protected、privateが存在してます。

publicは同じと捉えて良さそうなので、違う2つについて記述していきます。

private

違いが検証しやすかった方からのせます。
まずは下記のサンプルコードをご覧ください。

class A
    private def print
       p "a"
    end
end

class B < A
    def print2
        print
    end
end

b = B.new
b.print2

Javaと違ってクラス以外から使用してもRubyのprivateは動きます。
参考にさせていただいた記事を見るとprivate に設定されたメソッドは関数形式でしか呼び出せませんという記述になっているので、関数形式で呼び出せるサブクラスからも呼べてます。
きちんと動いていますが、Javaエンジニア的には少し気持ち悪いので注意が必要。

たぶん、他のケースでもアクセス出来ないと思ったら出来ちゃったがありそうです。

protected

色々調べたけど、良く分からないことが多いのと、生みの親であるMatzさんも今なら組み込まないと言われているというツイートを見かけたので見なかったことにします。

どうしても覚えなきゃいけないシーンに立ち会うまで初心者の方は見なかったことにしても良いかなと思います。

クラス

ここらへんは特に問題ありませんね。
使う側はクラス名.newという形で生成して使用します。

public class A {
}
class A
end

ただし、Rubyは以下のような形でclassの拡張が行えるので、やろうと思えばなんでもありで出来ます。

class A
    def print
       p "a"
    end
end

class A
    def print2
        p "b"
    end
end

a = A.new
a.print
a.print2

生成したインスタンスに対しての拡張も行えるので、本当になんでもありな世界を作ることが出来ます。
こちらは生成したインスタンスに限定出来るので、使い道がないとは言えないかもしれません。

class A
    def print
       p "a"
    end
end

a = A.new

# 特異クラスとして宣言する
class << a
    def print2
        p "b"
    end
end

a.print
a.print2

継承

JavaもRubyも継承は単一継承です。

ただしJavaはinterfaceなら複数個いけるので、ちょっと無理矢理なことも出来なくはないです(特にJava8以降)。

Rubyは言語的に抽象クラスや抽象メソッド、interfaceをサポートしていないようなので、完全に継承といったら単一のクラスの継承となります。
mixinとかdelegation(ライブラリを使用する必要あり)がありますが、そちらについては全く別の概念となっているようで、継承とは別と考えた方が良さそうです。(本記事では扱いません、moduleもいったん対象外とします)

public class A extends B {
}
class A < B
end

メソッド

メソッドは引数無しと有りで分けます。

引数無し

Rubyは()を省略することが可能となっています。
Rubyは特に戻り値の宣言が必要ないため、Docs書くなりしないと分かりづらいので注意が必要です。
Rubyの戻り値はreturnを記述するか、最後に評価された式の結果が返却されます。
Javaはreturnを明確に記述しないといけません。

public void method() {
    System.out.println("a");
}
def method
    print "a"
end

呼び出し時もRubyは省略可能となっています。
びっくりするから、無しの場合にどのような記述とするかはルールとして定めた方が良いと思います。

method()
method

引数有り

引数有りでもRubyは()を省略可能となっています。
呼び出し側も同様です。

public void method(String a, String b) {
    System.out.print(a);
    System.out.print(b);
}
def method a, b
    print a
    print b
end

メソッドのネスト

Javaでは出来ませんが、Rubyはメソッド内にメソッドが宣言出来ます。
使用についてはネストして宣言した後から使用出来、前からは使用出来ません。

def method
    print "a"

    def methtod2
        print "b"
    end

    methtod2
end

クラスメソッド

Rubyはクラスにメソッドを属することが出来ます。
Java的にはstaticメソッドと同様の使い方(考え方は違うと思います)が出来る感じです。

public class A {
    public static void main() {
        System.out.print("a");
    }
}
class A
    def self.method
        print "a"
    end
end

A::method

特異メソッドで宣言すればその中全てをクラスメソッドにすることも可能となっています。
複数のメソッドを定義する際に向いているとリファレンスには書いているため、分かりやすく分けてあげたほうが良いようです。

class A
    def print
       p "a"
    end
end

class << A
    def print2
        p "b"
    end
end

a = A.new
a.print
A::print2

単一でさらっとやりたい場合にはわざわざクラスから宣言せずともクラスメソッドを生成することも可能です。

def A.print2
    p "b"
end

おわりに

とりあえずばーっと書き出しましたが、混沌の原因を作りやすくなっているのでしっかりとチームルールを作って運用すべきだなと感じました。
そしてまだ書けてないことがありますが、とりあえず初心者がスタートするには過不足なさそうな感じがしたので、ここで止めておきます。

Javaがかっちりしているので、Rubyの自由さは混乱しちゃいますね。

0
0
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
0
0