English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Rubyは純面向オブジェクト言語であり、Rubyのすべてはオブジェクトの形で現れます。Rubyの各値はオブジェクトであり、最も原始的なもの:文字列、数字、trueとfalseもオブジェクトです。クラス自体もオブジェクト、 Class クラスの例。この章では、Rubyの面向オブジェクトに関する主要な機能すべてを説明します。
クラスはオブジェクトの形式を指定し、データ表現とメソッドを組み合わせて、データを整然とパッケージ化します。クラスのデータとメソッドはクラスのメンバーと呼ばれます。
クラスを定義する際には、実際にはデータの種類の設計図を定義しています。これは実際にはデータを定義していないことですが、クラスの名前が何を意味するか、つまり、クラスのオブジェクトが何で構成されているか、そのオブジェクトでどのような操作ができるかを定義しています。
クラス定義は、キーワード class を続け、クラス名、最後に end を使用して区切り、そのクラスの定義を終了します。例えば、以下のようにclassキーワードを使用してBoxクラスを定義します:
class Box code end
慣習に従って、名前は大文字で始まり、複数の単語を含む場合には、各単語の最初の文字が大文字になりますが、中間には区切り文字はありません(例:CamelCase)。
クラスはオブジェクトの設計図を提供するため、基本的には、オブジェクトはクラスに基づいて作成されます。以下のように new キーワードを使用してクラスのオブジェクトを宣言します。以下のステートメントは、クラスBoxの2つのオブジェクトを宣言しています:
box1 = Box.new box2 = Box.new
initialize メソッドは標準のRubyクラスメソッドであり、クラスの構造関数です。他の面向オブジェクトプログラミング言語の constructor 作成するオブジェクトにクラス変数を初期化する際に、initializeメソッドが役立ちます。このメソッドには、Rubyの他のメソッドと同様に、一連の引数が含まれており、このメソッドを使用する際には、前に def キーワードを使用して、以下のように示されます:
class Box def initialize(w,h) @width, @height = w, h end end
例変数クラス属性であり、クラスを使用してオブジェクトを作成すると、それがオブジェクトの属性になります。各オブジェクトの属性は個別に割り当てられ、他のオブジェクトとは値を共有しません。クラスの内部では、@演算子を使用してこれらの属性にアクセスし、クラスの外部では、呼ばれるアクセサメソッドの公共メソッドでアクセスします。以下に定義したクラス Box 例として、@widthと@heightをクラスBoxの例変数として使用します。
class Box def initialize(w,h) # 例変数に値を設定 @width, @height = w, h end end
クラス内に定義された変数を読み取るために外部からアクセスするには、アクセサ(getter)メソッドを定義してアクセスすることができます。以下の例では、アクセサメソッドの使用法を示します:
#!/usr/bin/ruby -w # クラスの定義 class Box # 架構関数 def initialize(w,h) @width, @height = w, h end # 访问器方法 def printWidth @width end def printHeight @height end end # オブジェクトの作成、ボックスの高さと幅の初期化 box = Box.new(10, 20) # 使用访问器方法 x = box.printWidth() y = box.printHeight() puts "ボックスの幅 : #{x}" puts "ボックスの高さ : #{y}"
上記のコードが実行されると、以下のような結果が得られます:
ボックスの幅 : 10 ボックスの高さ : 20
アクセサメソッドと同様に、Rubyはクラスの外部からパラメータをクラス内に定義された変数に渡す方法を提供します。これは、いわゆるセッター方法、以下のように定義されます:
#!/usr/bin/ruby -w # クラスの定義 class Box # 构造器メソッド def initialize(w,h) @width, @height = w, h end # 访问器方法 def getWidth @width end def getHeight @height end # 设置器方法 def setWidth=(value) @width = value end def setHeight=(value) @height = value end end # オブジェクトの作成 box = Box.new(10, 20) # セッター方法の使用 box.setWidth = 30 box.setHeight = 50 # 使用访问器方法 x = box.getWidth() y = box.getHeight() puts "ボックスの幅 : #{x}" puts "ボックスの高さ : #{y}"
上記のコードが実行されると、以下のような結果が得られます:
ボックスの幅 : 30 ボックスの高さ : 50
この二つの方法が非常に常用であるため、Rubyは以下を定義しました attr_accessor :variable_name、attr_reader :variable_name、attr_writer :variable_name 属性宣言の方法の三種類です。その中で:accessor=reader+writer
同時に注意してください:変数名の前に : を付け、変数名の間には , を使用してください。
例メソッドの定義は他のメソッドの定義と同様に、以下で使用されます def キーワードですが、それらはクラスの例を通じてのみ使用できます。以下の例のように。それらの機能は例変数にアクセスするに限られていません。必要に応じて他のタスクも行うことができます。
#!/usr/bin/ruby -w # クラスの定義 class Box # 架構メソッド def initialize(w,h) @width, @height = w, h end # 例メソッド def getArea @width * @height end end # オブジェクトの作成 box = Box.new(10, 20) # サンプルメソッドの呼び出し a = box.getArea() puts "箱の面積は: #{a}"
上記のコードが実行されると、以下のような結果が得られます:
箱の面積は: 200
クラス変数はクラスのすべての例で共有される変数です。言い換えれば、クラス変数の例はすべてのオブジェクトの例にアクセスできます。クラス変数は二つの @ 文字(@@)で接頭辞とされ、クラス変数はクラス定義内で初期化する必要があります。以下の例を参照してください。
クラスメソッドを使用します def self.methodname() 定義、クラスメソッドは end で区切られます。クラスメソッドはクラス名を含む classname.methodname 以下の例のように形式を呼び出します:
#!/usr/bin/ruby -w class Box # クラス変数の初期化 @@count = 0 def initialize(w,h) # 例変数に値を設定 @width, @height = w, h @@count += 1 end def self.printCount() puts "ボックスのカウントは:#@@count" end end # 创建两个对象 box1 = Box.new(10, 20) box2 = Box.new(3# 二つのオブジェクトを作成します 100) 0, # クラスメソッドを呼び出してボックスのカウントを出力します
上記のコードが実行されると、以下のような結果が得られます:
Box.printCount() 2
あなたが定義するどんなクラスにも、to_sメソッドがあります。 to_s 以下は、widthおよびheightに基づいてBoxオブジェクトを表現する簡単な例です。to_sメソッドを使用して、オブジェクトの文字列表現を返します。
#!/usr/bin/ruby -w class Box # 构造器メソッド def initialize(w,h) @width, @height = w, h end # to_sメソッドを定義します def to_s "(w:#@width,h:#@height)" # オブジェクトの文字列形式 end end # オブジェクトの作成 box = Box.new(10, 20) # to_sメソッドを自動的に呼び出します puts "boxの文字列表現は: #{box}"
上記のコードが実行されると、以下のような結果が得られます:
boxの文字列表現は: (w:10,h:20)
Rubyは三つのレベルのメソッド保護を提供しており、それぞれ public、privateまたはprotected。Rubyはサンプルおよびクラス変数にアクセス制御を適用しません。
publicメソッド: publicメソッドはどのオブジェクトでも呼び出すことができます。デフォルトでは、メソッドはすべてpublicですが、initializeメソッドは常にprivateです。
privateメソッド: privateメソッドは、クラス外部からアクセスまたは確認できません。クラスメソッドのみがプライベートメンバーにアクセスできます。
protectedメソッド: protectedメソッドは、そのクラスおよびそのサブクラスのオブジェクトによってのみ呼び出され、アクセスもそのクラスおよびそのサブクラス内でのみ行えます。
以下は、これら三つの修飾子の文法を示す簡単な例です:
#!/usr/bin/ruby -w # クラスの定義 class Box # 构造器メソッド def initialize(w,h) @width, @height = w, h end # サンプルメソッドはデフォルトでpublicです def getArea getWidth() * getHeight end # privateのアクセスメソッドを定義します def getWidth @width end def getHeight @height end # それらをprivateにします private :getWidth, :getHeight # 面積を出力するサンプルメソッド def printArea @area = getWidth() * getHeight puts "大きなboxの面積は:" + @area end # サンプルメソッドをprotectedに設定します protected :printArea end # オブジェクトの作成 box = Box.new(10, 20) # サンプルメソッドの呼び出し a = box.getArea() puts "箱の面積は: #{a}" # protectedのサンプルメソッドの呼び出しを試みます box.printArea()
上記のコードが実行されたとき、以下の結果が得られます。ここでは、最初のメソッドの呼び出しが成功しましたが、二つ目のメソッドには問題が発生しました。
箱の面積は: 200 test.rb:42: protected method `printArea' called for # <Box:0xb7f11280 @height=20, @width=10> (NoMethodError)
継承をサポートしており、これはオブジェクト指向プログラミングの中で最も重要な概念の1つです。継承は、他のクラスを基にクラスを定義することを許可し、アプリケーションの作成と保守をより簡単にします。
継承は、コードの再利用と迅速な実行を助けますが、不幸なことに、Rubyは多継承をサポートしていません。しかし、Rubyは mixinは、多継承の特定の実現として考えられます。多継承では、インターフェース部分のみが継承されます。と呼ばれます。
クラスを作成する際に、プログラマーは直接、新たなクラスが特定の既存クラスのメンバーを継承するように指定できます。これにより、新しいデータメンバーとメンバー関数を手動で書き直す必要がありません。その既存クラスは基底クラスまたは親クラスと呼ばれます。派生クラスまたはサブクラス
Rubyもサブクラス化の概念を提供しており、サブクラス化とは、継承のことです。以下の例ではこの概念を説明しています。クラスを拡張する语法は非常にシンプルです。クラス宣言に < と親クラスの名前を追加するだけで良いです。例えば、以下のように定義されています。 BigBox は Box のサブクラス:
#!/usr/bin/ruby -w # クラスの定義 class Box # 构造器メソッド def initialize(w,h) @width, @height = w, h end # 例メソッド def getArea @width * @height end end # 子クラスを定義する class BigBox < Box # 新しいサンプルメソッドを追加する def printArea @area = @width * @height puts "大きなboxの面積は:" + @area end end # オブジェクトの作成 box = BigBox.new(10, 20) # 面積を出力する box.printArea()
上記のコードが実行されると、以下のような結果が得られます:
大きなboxの面積は: 200
派生クラスに新しい機能を追加できる場合がありますが、時には親クラスで既に定義されているメソッドの動作を変更したい場合もあります。その場合、メソッド名を変更せずに機能をオーバーロードするだけで良い、以下の例を参照してください:
#!/usr/bin/ruby -w # クラスの定義 class Box # 构造器メソッド def initialize(w,h) @width, @height = w, h end # 例メソッド def getArea @width * @height end end # 子クラスを定義する class BigBox < Box # 已存のgetAreaメソッドを変更する def getArea @area = @width * @height puts "大きなboxの面積は:" + @area end end # オブジェクトの作成 box = BigBox.new(10, 20) # オーバーロードされたメソッドを使って面積を出力する box.getArea()
以下の例の実行結果は:
大きなboxの面積は: 200
以下のように使用したいです + 演算子を用いて二つのBoxオブジェクトのベクトル加法を実行します、以下のように使用します * 演算子を用いてBoxのwidthとheightを乗算させる、一元演算子を使います - Boxのwidthとheightを反転させる。以下は、数学演算子の定義を持つBoxクラスのバージョンです:
class Box def initialize(w,h) # width と height を初期化する @width, @height = w, h end def +(other) # 定義 + ベクトル加法を実行する Box.new(@width + other.width, @height + other.height) end def -# 一元演算子を定義する - width と height を反転させる Box.new(-@width, -@height) end def *(scalar) # 执行标量乘法 Box.new(@width*scalar, @height*scalar) end end
有时候,我们想要防止对象被改变。在 Object 中,freeze 方法可实现这点,它能有效地把一个对象变成一个常量。任何对象都可以通过调用 Object.freeze 进行冻结。冻结对象不能被修改,也就是说,您不能改变它的示例变量。
您可以使用 Object.frozen? 方法检查一个给定的对象是否已经被冻结。如果对象已被冻结,该方法将返回 true,否则返回一个 false 值。下面的示例解释了这个概念:
#!/usr/bin/ruby -w # クラスの定義 class Box # 构造器メソッド def initialize(w,h) @width, @height = w, h end # 访问器方法 def getWidth @width end def getHeight @height end # 设置器方法 def setWidth=(value) @width = value end def setHeight=(value) @height = value end end # オブジェクトの作成 box = Box.new(10, 20) # 让我们冻结该对象 box.freeze if( box.frozen? ) puts "Box object is frozen object" else puts "Box object is normal object" end # 现在尝试使用设置器方法 box.setWidth = 30 box.setHeight = 50 # 使用访问器方法 x = box.getWidth() y = box.getHeight() puts "Width of the box is : #{x}" puts "Height of the box is : #{y}"
上記のコードが実行されると、以下のような結果が得られます:
Box object is frozen object test.rb:20:in `setWidth=': can't modify frozen object (TypeError) from test.rb:39
您可以在类的内部定义一个常量,通过把一个直接的数值或字符串值赋给一个变量来定义的,常量的定义不需要使用 @ 或 @@。按照惯例,常量的名称使用大写。
一旦常量被定义,您就不能改变它的值,您可以在类的内部直接访问常量,就像是访问变量一样,但是如果您想要在类的外部访问常量,那么您必须使用 classname::constant、以下の例を参照してください。
#!/usr/bin/ruby -w # クラスの定義 class Box BOX_COMPANY = "TATA Inc" BOXWEIGHT = 10 # 构造器メソッド def initialize(w,h) @width, @height = w, h end # 例メソッド def getArea @width * @height end end # オブジェクトの作成 box = Box.new(10, 20) # サンプルメソッドの呼び出し a = box.getArea() puts "箱の面積は: #{a}" puts Box::BOX_COMPANY puts "Boxの重さは: #{Box::BOXWEIGHT}"
上記のコードが実行されると、以下のような結果が得られます:
箱の面積は: 200 TATA Inc Boxの重さは: 10
クラスの常量は継承され、例メソッドのようにオーバーライドもできます。
ある場合、オブジェクトのコンストラクタを呼び出さずにオブジェクトを作成したいかもしれません。 initialize この場合、newメソッドを使用してオブジェクトを作成するとき、未初期化のオブジェクトを作成するためにallocateを呼び出すことができます。以下の例を参照してください:
#!/usr/bin/ruby -w # クラスの定義 class Box attr_accessor :width, :height # 构造器メソッド def initialize(w,h) @width, @height = w, h end # 例メソッド def getArea @width * @height end end # newを使用してオブジェクトを作成 box1 = Box.new(10, 20) # allocateを使用して別のオブジェクトを作成 box2 = Box.allocate # boxを使用1 サンプルメソッドの呼び出し a = box1.getArea() puts "箱の面積は: #{a}" # boxを使用2 サンプルメソッドの呼び出し a = box2.getArea() puts "箱の面積は: #{a}"
上記のコードが実行されると、以下のような結果が得られます:
箱の面積は: 200 test.rb:14: warning: instance variable @width not initialized test.rb:14: warning: instance variable @height not initialized test.rb:14:in `getArea`: undefined method `*" for nil:NilClass (NoMethodError) from test.rb:29
RubyのselfとJavaのthisは似ている部分があるが、大きく異なる。Javaのメソッドは例メソッドから参照されるため、thisは通常現在のオブジェクトを指している。一方、Rubyのコードは逐行実行されるため、異なる文脈(context)でselfには異なる意味がある。以下の例を見てみよう:。
#!/usr/bin/ruby -w class Box # クラス情報を出力 puts "selfのクラス = #{self.class}" puts "selfの名前 = #{self.name}" end
上記のコードが実行されると、以下のような結果が得られます:
selfのクラス = Class selfの名前 = Box
これは、クラス定義がそのクラスを現在のオブジェクトとして実行できることを意味し、同時にメタクラスと親クラスの该方法がメソッド定義の実行中に利用できることを意味します。