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}"
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}"
Area of the box is : 200 TATA Inc Box weight is: 10Pemalar 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.