Ruby berorientasikan objek


Ruby ialah bahasa berorientasikan objek semata-mata, dan segala-galanya dalam Ruby muncul dalam bentuk objek. Setiap nilai dalam Ruby ialah objek, malah perkara yang paling primitif: rentetan, nombor, malah benar dan palsu ialah objek. Kelas itu sendiri juga merupakan Objek, yang merupakan contoh kelas Kelas. Bab ini akan mengajar anda tentang semua ciri utama yang berkaitan dengan Ruby berorientasikan objek. Kelas

digunakan untuk menentukan bentuk objek, yang menggabungkan perwakilan data dan kaedah untuk menyusun data ke dalam pakej yang kemas. Data dan kaedah dalam kelas dipanggil ahli kelas.

Definisi Kelas Ruby

Apabila anda mentakrifkan kelas, anda sebenarnya mentakrifkan pelan tindakan jenis data. Ini sebenarnya tidak mentakrifkan sebarang data, sebaliknya mentakrifkan maksud nama kelas, iaitu, objek kelas akan terdiri daripada, dan operasi yang boleh dilakukan pada objek.

Takrif kelas bermula dengan kata kunci kelas, diikuti dengan nama kelas dan akhirnya dipisahkan dengan akhir untuk menamatkan definisi kelas . Sebagai contoh, kami menggunakan kelas kata kunci untuk mentakrifkan kelas Box seperti berikut:

class Box
   code
end

Mengikut konvensyen, nama mesti bermula dengan huruf besar Jika ia mengandungi berbilang perkataan, huruf pertama setiap perkataan ditulis dengan huruf besar. tetapi tidak ada pemisahan antara mereka (contohnya: CamelCase).

Mentakrifkan Objek Ruby

Kelas menyediakan rangka tindakan objek, jadi pada asasnya, objek dicipta berdasarkan kelas. Kami mengisytiharkan objek kelas menggunakan kata kunci baharu. Pernyataan berikut mengisytiharkan dua objek kotak kelas:

box1 = Box.new
box2 = Box.new

kaedah permulaan

permulaan kaedah ialah kaedah kelas Ruby standard, yang merupakan pembina kelas, dan pembina dalam bahasa pengaturcaraan berorientasikan objek lain berfungsi sama. Kaedah permulaan berguna apabila anda ingin memulakan beberapa pembolehubah kelas semasa mencipta objek. Kaedah ini mengambil satu siri parameter Seperti kaedah Ruby yang lain, apabila menggunakan kaedah ini, anda mesti meletakkan kata kunci def di hadapan, seperti berikut:

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

Pembolehubah instance

Pembolehubah instance ialah atribut kelas dan ia menjadi atribut objek apabila menggunakan kelas untuk mencipta objek. Sifat setiap objek diberikan secara individu dan tidak berkongsi nilai dengan objek lain. Di dalam kelas, sifat ini diakses menggunakan operator @, dan di luar kelas, ia diakses menggunakan kaedah awam yang dipanggil Kaedah Aksesor. Di bawah ini kita ambil kelas Kotak yang ditakrifkan di atas sebagai contoh, dan gunakan @width dan @height sebagai pembolehubah contoh bagi Kelas Box.

class Box
   def initialize(w,h)
      # 给实例变量赋值
      @width, @height = w, h
   end
end

Kaedah Aksesor & Penetap

Untuk menggunakan pembolehubah di luar kelas, kita perlu mentakrifkan pembolehubah ini di dalam Kaedah Aksesor, aksesor sebenarnya bersamaan dengan getter. Contoh berikut menunjukkan penggunaan kaedah pengakses:

#!/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 "Width of the box is : #{x}"
puts "Height of the box is : #{y}"


Apabila kod di atas dilaksanakan, ia menghasilkan hasil berikut:

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

adalah sama seperti yang digunakan untuk kaedah Accessor untuk mengakses nilai pembolehubah adalah serupa Ruby menyediakan cara untuk menetapkan nilai pembolehubah di luar kelas, iaitu apa yang dipanggil kaedah penetap, yang ditakrifkan seperti berikut: <. 🎜>

#!/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 "Width of the box is : #{x}"
puts "Height of the box is : #{y}"


Apabila kod di atas dilaksanakan, ia menghasilkan keputusan berikut:

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

Kaedah contoh

Takrif kaedah contoh adalah sama dengan takrifan kaedah lain, menggunakan kata kunci def, tetapi ia hanya boleh diakses melalui contoh kelas Gunakan, seperti yang ditunjukkan dalam contoh di bawah. Fungsi mereka tidak terhad kepada mengakses pembolehubah contoh, tetapi juga boleh melakukan banyak tugas lain mengikut keperluan anda.

#!/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 "Area of the box is : #{a}"


Apabila kod di atas dilaksanakan, ia akan menghasilkan keputusan berikut:

Area of the box is : 200

Kaedah Kelas & Pembolehubah Kelas

Pembolehubah kelas ialah pembolehubah yang dikongsi antara semua kejadian kelas. Dalam erti kata lain, contoh pembolehubah kelas boleh diakses oleh semua contoh objek. Pembolehubah kelas diawali dengan dua aksara @ (@@) dan mesti dimulakan dalam definisi kelas, seperti yang ditunjukkan dalam contoh berikut.

Kaedah kelas ditakrifkan menggunakan def self.methodname() kaedah kelas berakhir dengan pembatas akhir. Kaedah kelas boleh dipanggil menggunakan borang classname.methodname dengan nama kelas, seperti yang ditunjukkan dalam contoh berikut:

#!/usr/bin/ruby -w

class Box
   # 初始化类变量
   @@count = 0
   def initialize(w,h)
      # 给实例变量赋值
      @width, @height = w, h

      @@count += 1
   end

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

# 创建两个对象
box1 = Box.new(10, 20)
box2 = Box.new(30, 100)

# 调用类方法来输出盒子计数
Box.printCount()


Apabila kod di atas adalah dilaksanakan, Ia menghasilkan hasil berikut:

Box count is : 2

kaedah to_s

Mana-mana kelas yang anda takrifkan mempunyai kaedah contoh to_s yang mengembalikan perwakilan rentetan objek. Berikut ialah contoh mudah yang mewakili objek Kotak dari segi lebar dan tinggi:

#!/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 "String representation of box is : #{box}"


Apabila kod di atas dilaksanakan, ia akan menghasilkan keputusan berikut:

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

Kawalan Akses

Ruby memberi anda tiga tahap perlindungan kaedah contoh, iaitu awam, peribadi atau dilindungi. Ruby tidak menggunakan sebarang kawalan akses pada pembolehubah contoh dan kelas.

  • Kaedah awam: Kaedah awam boleh dipanggil oleh mana-mana objek. Secara lalai, kaedah semuanya awam, kecuali kaedah permulaan yang sentiasa peribadi.

  • Kaedah peribadi: Kaedah persendirian tidak boleh diakses atau dilihat dari luar kelas. Hanya kaedah kelas boleh mengakses ahli persendirian.

  • Kaedah yang dilindungi: Kaedah yang dilindungi hanya boleh dipanggil oleh objek kelas dan subkelasnya. Akses juga hanya boleh dilakukan dalam kelas dan subkelasnya.

Berikut ialah contoh mudah yang menunjukkan sintaks ketiga-tiga pengubah ini:

#!/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
   # make them private
   private :getWidth, :getHeight

   # 用于输出面积的实例方法
   def printArea
      @area = getWidth() * getHeight
      puts "Big box area is : #@area"
   end
   # 让实例方法是 protected 的
   protected :printArea
end

# 创建对象
box = Box.new(10, 20)

# 调用实例方法
a = box.getArea()
puts "Area of the box is : #{a}"

# 尝试调用 protected 的实例方法
box.printArea()


Apabila kod di atas dilaksanakan, ia menghasilkan keputusan berikut. Di sini, panggilan kaedah pertama berjaya, tetapi kaedah kedua menimbulkan masalah.

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

Warisan kelas

Warisan ialah salah satu konsep terpenting dalam pengaturcaraan berorientasikan objek. Warisan membolehkan kami mentakrifkan kelas berdasarkan kelas lain, menjadikannya lebih mudah untuk mencipta dan menyelenggara aplikasi.

Warisan membantu dengan penggunaan semula kod dan pelaksanaan pantas, malangnya Ruby tidak menyokong berbilang warisan, tetapi Ruby menyokong campuran. Mixin adalah seperti pelaksanaan khusus bagi pelbagai warisan, di mana hanya bahagian antara muka boleh diwarisi.

Apabila mencipta kelas, pengaturcara boleh menentukan secara langsung bahawa kelas baharu mewarisi ahli kelas sedia ada, jadi tidak perlu menulis ahli data baharu dan fungsi ahli dari awal. Kelas sedia ada ini dipanggil kelas asas atau kelas induk dan kelas baharu dipanggil kelas terbitan atau subkelas.

Ruby juga menyediakan konsep subkelas, iaitu pewarisan Contoh berikut menerangkan konsep ini. Sintaks untuk melanjutkan kelas adalah sangat mudah. Hanya tambahkan aksara < dan nama kelas induk pada pernyataan kelas. Sebagai contoh, yang berikut mentakrifkan kelas BigBox yang merupakan subkelas 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 "Big box area is : #@area"
   end
end

# 创建对象
box = BigBox.new(10, 20)

# 输出面积
box.printArea()


Apabila kod di atas dilaksanakan , ia akan Menghasilkan hasil berikut:

Big box area is : 200

Metode Overloading

Walaupun anda boleh menambah fungsi baharu dalam kelas terbitan, kadangkala anda mungkin mahu menukar tingkah laku kaedah yang telah ditakrifkan dalam kelas induk. Pada masa ini, anda boleh mengekalkan nama kaedah tidak berubah dan melebihkan fungsi kaedah, seperti yang ditunjukkan dalam contoh berikut:

#!/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 "Big box area is : #@area"
   end
end

# 创建对象
box = BigBox.new(10, 20)

# 使用重载的方法输出面积
box.getArea()


Hasil keluaran contoh di atas ialah :

Big box area is : 200

Operator overloading

Kami ingin menggunakan operator + untuk melakukan penambahan vektor bagi dua objek Kotak, gunakan operator * untuk mendarab lebar dan tinggi Kotak, dan gunakan unary operator - untuk lebar Kotak Negatif ketinggian. Berikut ialah versi kelas Box dengan definisi pengendali matematik:

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

Objek Pembekuan

Kadangkala, kami mahu menghalang objek daripada ditukar. Dalam Objek, ini dicapai dengan kaedah pembekuan, yang secara berkesan mengubah objek menjadi pemalar. Mana-mana objek boleh dibekukan dengan memanggil Object.freeze. Objek beku tidak boleh diubah suai, iaitu, anda tidak boleh menukar pembolehubah contohnya.

Anda boleh menyemak sama ada objek yang diberikan telah dibekukan menggunakan kaedah Object.frozen?. Kaedah ini mengembalikan benar jika objek telah dibekukan, jika tidak ia mengembalikan nilai palsu. Contoh berikut menerangkan konsep ini:

#!/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}"


Apabila kod di atas dilaksanakan, ia akan menghasilkan hasil berikut:

Box object is frozen object
test.rb:20:in `setWidth=': can't modify frozen object (TypeError)
        from test.rb:39

Malar Kelas

Anda boleh menentukan pemalar di dalam kelas dengan memberikan nilai angka atau rentetan langsung kepada pembolehubah Takrif pemalar tidak memerlukan penggunaan @ atau @. Mengikut konvensyen, nama tetap adalah dalam huruf besar.

Setelah pemalar ditakrifkan, anda tidak boleh menukar nilainya Anda boleh mengakses pemalar terus di dalam kelas sama seperti pembolehubah, tetapi jika anda ingin mengakses pemalar di luar kelas, maka anda Mesti gunakan <🎜. >classname::constant, seperti yang ditunjukkan dalam contoh di bawah.

#!/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 "Area of the box is : #{a}"
puts Box::BOX_COMPANY
puts "Box weight is: #{Box::BOXWEIGHT}"


Apabila kod di atas dilaksanakan, ia akan menghasilkan keputusan berikut:

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

Pemalar kelas boleh diwarisi dan juga boleh ditindih seperti kaedah contoh memuatkan.

Mencipta objek menggunakan memperuntukkan

Mungkin terdapat situasi di mana anda ingin mencipta objek tanpa memanggil pembina objek

memulakan, iaitu mencipta objek menggunakan kaedah baharu , dalam hal ini anda boleh memanggil peruntukan untuk mencipta objek yang tidak dimulakan, seperti yang ditunjukkan dalam contoh berikut:

#!/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

# 使用 box1 调用实例方法
a = box1.getArea()
puts "Area of the box is : #{a}"

# 使用 box2 调用实例方法
a = box2.getArea()
puts "Area of the box is : #{a}"


Apabila kod di atas dilaksanakan, ia menghasilkan hasil berikut:

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

Maklumat kelas

Diri Ruby dan Java ini mempunyai persamaan, tetapi mereka juga sangat berbeza. Kaedah Java dirujuk dalam kaedah contoh, jadi ini biasanya menunjuk kepada objek semasa. Kod Ruby dilaksanakan baris demi baris, jadi diri mempunyai makna yang berbeza dalam konteks yang berbeza. Mari kita lihat contoh berikut: .

#!/usr/bin/ruby -w

class Box
   # 输出类信息
   puts "Class of self = #{self.class}"
   puts "Name of self = #{self.name}"
end


Apabila kod di atas dilaksanakan, ia akan menghasilkan keputusan berikut:

Class of self = Class
Name of self = Box

Ini bermakna class Definisi boleh dilaksanakan dengan menjadikan kelas sebagai objek semasa, yang juga bermakna kaedah dalam metaclass dan superclass tersedia semasa pelaksanaan definisi kaedah.