Ruby-オブジェクト指向

Rubyは純粋なオブジェクト指向言語であり、すべてがオブジェクトとしてRubyに表示されます。Rubyのすべての値はオブジェクトであり、最も原始的なものでさえ、文字列、数値、さらにはtrueとfalseです。クラス自体でさえ、Classクラスのインスタンスであるオブジェクトです。この章では、オブジェクト指向Rubyに関連するすべての主要な機能について説明します。

クラスはオブジェクトの形式を指定するために使用され、データ表現とそのデータを操作するためのメソッドを1つのきちんとしたパッケージに結合します。クラス内のデータとメソッドは、クラスのメンバーと呼ばれます。

Rubyクラスの定義

クラスを定義するときは、データ型の青写真を定義します。これは実際にはデータを定義しませんが、クラス名の意味、つまり、クラスのオブジェクトが何で構成され、そのようなオブジェクトに対してどのような操作を実行できるかを定義します。

クラス定義はキーワードで始まります class 続いて class name で区切られています end。たとえば、キーワードクラスを使用してBoxクラスを次のように定義しました-

class Box
   code
end

名前は大文字で始まる必要があり、慣例により、複数の単語を含む名前は、大文字で区切られた各単語と一緒に実行され、区切り文字は使用されません(CamelCase)。

Rubyオブジェクトを定義する

クラスはオブジェクトの青写真を提供するため、基本的にオブジェクトはクラスから作成されます。を使用してクラスのオブジェクトを宣言しますnewキーワード。次のステートメントは、クラスBox −の2つのオブジェクトを宣言します。

box1 = Box.new
box2 = Box.new

初期化メソッド

ザ・ initialize method は標準のRubyクラスメソッドであり、とほぼ同じように機能します。 constructor他のオブジェクト指向プログラミング言語で動作します。initializeメソッドは、オブジェクトの作成時にいくつかのクラス変数を初期化する場合に役立ちます。このメソッドはパラメータのリストを取得する場合があり、他のrubyメソッドと同様に、その前にdef 以下に示すキーワード-

class Box
   def initialize(w,h)
      @width, @height = w, h
   end
end

インスタンス変数

ザ・ instance variablesは一種のクラス属性であり、クラスを使用してオブジェクトが作成されると、オブジェクトのプロパティになります。すべてのオブジェクトの属性は個別に割り当てられ、他のオブジェクトと値を共有しません。これらはクラス内で@演算子を使用してアクセスされますが、クラス外でアクセスするために使用しますpublic と呼ばれるメソッド accessor methods。上記で定義されたクラスを取る場合Box その場合、@ widthと@heightはクラスBoxのインスタンス変数です。

class Box
   def initialize(w,h)
      # assign instance variables
      @width, @height = w, h
   end
end

アクセサーとセッターのメソッド

クラスの外部から変数を使用できるようにするには、変数をクラス内で定義する必要があります。 accessor methods、これらのアクセサメソッドはゲッターメソッドとも呼ばれます。次の例は、アクセサメソッドの使用法を示しています-

#!/usr/bin/ruby -w

# define a class
class Box
   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end

   # accessor methods
   def printWidth
      @width
   end

   def printHeight
      @height
   end
end

# create an object
box = Box.new(10, 20)

# use accessor methods
x = box.printWidth()
y = box.printHeight()

puts "Width of the box is : #{x}"
puts "Height of the box is : #{y}"

上記のコードを実行すると、次の結果が得られます。

Width of the box is : 10
Height of the box is : 20

変数の値にアクセスするために使用されるアクセサメソッドと同様に、Rubyは、を使用してクラスの外部からそれらの変数の値を設定する方法を提供します。 setter methods、以下のように定義されます-

#!/usr/bin/ruby -w

# define a class
class Box
   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end

   # accessor methods
   def getWidth
      @width
   end
   def getHeight
      @height
   end

   # setter methods
   def setWidth=(value)
      @width = value
   end
   def setHeight=(value)
      @height = value
   end
end

# create an object
box = Box.new(10, 20)

# use setter methods
box.setWidth = 30
box.setHeight = 50

# use accessor methods
x = box.getWidth()
y = box.getHeight()

puts "Width of the box is : #{x}"
puts "Height of the box is : #{y}"

上記のコードを実行すると、次の結果が得られます。

Width of the box is : 30
Height of the box is : 50

インスタンスメソッド

ザ・ instance methods を使用して他のメソッドを定義するのと同じ方法で定義されます defキーワードであり、以下に示すように、クラスインスタンスを使用してのみ使用できます。それらの機能は、インスタンス変数へのアクセスに限定されていませんが、要件に応じてさらに多くのことを実行できます。

#!/usr/bin/ruby -w

# define a class
class Box
   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end
   # instance method
   def getArea
      @width * @height
   end
end

# create an object
box = Box.new(10, 20)

# call instance methods
a = box.getArea()
puts "Area of the box is : #{a}"

上記のコードを実行すると、次の結果が得られます。

Area of the box is : 200

クラスメソッドと変数

ザ・ class variablesクラスのすべてのインスタンス間で共有される変数です。つまり、変数のインスタンスが1つあり、オブジェクトインスタンスからアクセスされます。クラス変数の前には2つの@文字(@@)が付いています。以下に示すように、クラス変数はクラス定義内で初期化する必要があります。

クラスメソッドは、を使用して定義されます def self.methodname()、終了区切り文字で終わり、クラス名を使用して呼び出されます。 classname.methodname 次の例に示すように-

#!/usr/bin/ruby -w

class Box
   # Initialize our class variables
   @@count = 0
   def initialize(w,h)
      # assign instance avriables
      @width, @height = w, h

      @@count += 1
   end

   def self.printCount()
      puts "Box count is : #@@count"
   end
end

# create two object
box1 = Box.new(10, 20)
box2 = Box.new(30, 100)

# call class method to print box count
Box.printCount()

上記のコードを実行すると、次の結果が得られます。

Box count is : 2

to_sメソッド

定義するクラスには、 to_sオブジェクトの文字列表現を返すインスタンスメソッド。以下は、幅と高さの観点からBoxオブジェクトを表す簡単な例です。

#!/usr/bin/ruby -w

class Box
   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end
   # define to_s method
   def to_s
      "(w:#@width,h:#@height)"  # string formatting of the object.
   end
end

# create an object
box = Box.new(10, 20)

# to_s method will be called in reference of string automatically.
puts "String representation of box is : #{box}"

上記のコードを実行すると、次の結果が得られます。

String representation of box is : (w:10,h:20)

アクセス制御

Rubyは、インスタンスメソッドレベルで3つのレベルの保護を提供します。 public, private, or protected。Rubyは、インスタンス変数とクラス変数にアクセス制御を適用しません。

  • Public Methods−パブリックメソッドは誰でも呼び出すことができます。メソッドは、常にプライベートである初期化を除いて、デフォルトでパブリックです。

  • Private Methods−プライベートメソッドにアクセスしたり、クラスの外部から表示したりすることはできません。クラスメソッドのみがプライベートメンバーにアクセスできます。

  • Protected Methods−保護されたメソッドは、定義クラスとそのサブクラスのオブジェクトによってのみ呼び出すことができます。アクセスは家族内で維持されます。

以下は、3つのアクセス修飾子すべての構文を示す簡単な例です-

#!/usr/bin/ruby -w

# define a class
class Box
   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end

   # instance method by default it is public
   def getArea
      getWidth() * getHeight
   end

   # define private accessor methods
   def getWidth
      @width
   end
   def getHeight
      @height
   end
   # make them private
   private :getWidth, :getHeight

   # instance method to print area
   def printArea
      @area = getWidth() * getHeight
      puts "Big box area is : #@area"
   end
   # make it protected
   protected :printArea
end

# create an object
box = Box.new(10, 20)

# call instance methods
a = box.getArea()
puts "Area of the box is : #{a}"

# try to call protected or methods
box.printArea()

上記のコードを実行すると、次のような結果になります。ここでは、最初のメソッドが正常に呼び出されましたが、2番目のメソッドで問題が発生しました。

Area of the box is : 200
test.rb:42: protected method `printArea' called for #
<Box:0xb7f11280 @height = 20, @width = 10> (NoMethodError)

クラスの継承

オブジェクト指向プログラミングで最も重要な概念の1つは、継承の概念です。継承により、別のクラスの観点からクラスを定義できるため、アプリケーションの作成と保守が容易になります。

継承は、コード機能と迅速な実装時間を再利用する機会も提供しますが、残念ながら、Rubyは複数レベルの継承をサポートしていませんが、Rubyはサポートしています。 mixins。ミックスインは、インターフェイス部分のみが継承される多重継承の特殊な実装のようなものです。

クラスを作成するとき、プログラマーは、完全に新しいデータメンバーとメンバー関数を作成する代わりに、新しいクラスが既存のクラスのメンバーを継承するように指定できます。この既存のクラスは、base class or superclass、および新しいクラスは、 derived class or sub-class

Rubyは、サブクラス化の概念、つまり継承もサポートしています。次の例で概念を説明します。クラスを拡張するための構文は単純です。<文字とスーパークラスの名前をクラスステートメントに追加するだけです。たとえば、以下では、クラスBigBoxBox −のサブクラスとして定義します。

#!/usr/bin/ruby -w

# define a class
class Box
   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end
   # instance method
   def getArea
      @width * @height
   end
end

# define a subclass
class BigBox < Box

   # add a new instance method
   def printArea
      @area = @width * @height
      puts "Big box area is : #@area"
   end
end

# create an object
box = BigBox.new(10, 20)

# print the area
box.printArea()

上記のコードを実行すると、次の結果が得られます。

Big box area is : 200

メソッドのオーバーライド

派生クラスに新しい機能を追加することはできますが、親クラスですでに定義されているメソッドの動作を変更したい場合があります。以下の例に示すように、メソッド名を同じに保ち、メソッドの機能をオーバーライドするだけで、これを行うことができます。

#!/usr/bin/ruby -w

# define a class
class Box
   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end
   # instance method
   def getArea
      @width * @height
   end
end

# define a subclass
class BigBox < Box

   # change existing getArea method as follows
   def getArea
      @area = @width * @height
      puts "Big box area is : #@area"
   end
end

# create an object
box = BigBox.new(10, 20)

# print the area using overriden method.
box.getArea()

演算子のオーバーロード

+演算子で+を使用して2つのBoxオブジェクトのベクトル加算を実行し、*演算子でボックスの幅と高さをスカラーで乗算し、単項-演算子でボックスの幅と高さを無効にします。これは、数学演算子が定義されたBoxクラスのバージョンです-

class Box
   def initialize(w,h)     # Initialize the width and height
      @width,@height = w, h
   end

   def +(other)       # Define + to do vector addition
      Box.new(@width + other.width, @height + other.height)
   end

   def -@           # Define unary minus to negate width and height
      Box.new(-@width, -@height)
   end

   def *(scalar)           # To perform scalar multiplication
      Box.new(@width*scalar, @height*scalar)
   end
end

オブジェクトの凍結

オブジェクトが変更されないようにしたい場合があります。Objectのfreezeメソッドを使用すると、これを実行して、オブジェクトを効果的に定数に変換できます。を呼び出すことで、任意のオブジェクトをフリーズできますObject.freeze。フリーズされたオブジェクトは変更できません。インスタンス変数を変更することはできません。

特定のオブジェクトがすでにフリーズされているかどうか、または使用していないかどうかを確認できます Object.frozen?メソッド。オブジェクトがフリーズした場合はtrueを返し、それ以外の場合はfalse値を返します。次の例は概念をクリアします-

#!/usr/bin/ruby -w

# define a class
class Box
   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end

   # accessor methods
   def getWidth
      @width
   end
   def getHeight
      @height
   end

   # setter methods
   def setWidth=(value)
      @width = value
   end
   def setHeight=(value)
      @height = value
   end
end

# create an object
box = Box.new(10, 20)

# let us freez this object
box.freeze
if( box.frozen? )
   puts "Box object is frozen object"
else
   puts "Box object is normal object"
end

# now try using setter methods
box.setWidth = 30
box.setHeight = 50

# use accessor methods
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

# define a class
class Box
   BOX_COMPANY = "TATA Inc"
   BOXWEIGHT = 10
   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end
   # instance method
   def getArea
      @width * @height
   end
end

# create an object
box = Box.new(10, 20)

# call instance methods
a = box.getArea()
puts "Area of the box is : #{a}"
puts Box::BOX_COMPANY
puts "Box weight is: #{Box::BOXWEIGHT}"

上記のコードを実行すると、次の結果が得られます。

Area of the box is : 200
TATA Inc
Box weight is: 10

クラス定数は継承され、インスタンスメソッドのようにオーバーライドできます。

Allocateを使用してオブジェクトを作成する

コンストラクターを呼び出さずにオブジェクトを作成したい場合があります initializeつまり、新しいメソッドを使用します。このような場合、allocateを呼び出すことができます。これにより、次の例のように、初期化されていないオブジェクトが作成されます。

#!/usr/bin/ruby -w

# define a class
class Box
   attr_accessor :width, :height

   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end

   # instance method
   def getArea
      @width * @height
   end
end

# create an object using new
box1 = Box.new(10, 20)

# create another object using allocate
box2 = Box.allocate

# call instance method using box1
a = box1.getArea()
puts "Area of the box is : #{a}"

# call instance method using box2
a = box2.getArea()
puts "Area of the box is : #{a}"

上記のコードを実行すると、次の結果が得られます。

Area of the box is : 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

クラス情報

クラス定義が実行可能コードである場合、これは、それらが何らかのオブジェクトのコンテキストで実行されることを意味します。selfは何かを参照する必要があります。それが何であるかを調べましょう。

#!/usr/bin/ruby -w

class Box
   # print class information
   puts "Type of self = #{self.type}"
   puts "Name of self = #{self.name}"
end

上記のコードを実行すると、次の結果が得られます。

Type of self = Class
Name of self = Box

これは、クラス定義がそのクラスを現在のオブジェクトとして実行されることを意味します。これは、メタクラスとそのスーパークラスのメソッドが、メソッド定義の実行中に使用可能になることを意味します。