Saat ini saya sedang mempelajari dasar-dasar Ruby dan OOP secara umum. Dari apa yang saya baca sejauh ini, saya dapat menggunakan attr_reader untuk mengambil nilai variabel instan tetapi tidak memberikannya akses untuk ditimpa. Namun, mengingat blok kode di bawah ini, hasil akhirnya tidak seperti yang saya maksudkan dan variabel instan benar-benar berubah dari luar kelas. Apa cara terbaik di mana saya bisa membaca nilainya dan mengembalikan perubahan yang diinginkan ke variabel lain alih-alih menimpa variabel instan itu sendiri?

class X
  def initialize
    @y = [1,2,3,4]
  end
  attr_reader :y
end

class Z
  def initialize
  end
  def self.change(arr)
    arr[1] = 0
    arr[2] = 0
    return arr
  end
end

x = X.new
z = Z.change(x.y)
p z
p x.y
1
OPB 15 Januari 2021, 11:09

2 jawaban

Jawaban Terbaik

Dengan menggunakan clone: https:// ruby-doc.org/core-2.7.2/Object.html#method-i-clone

Menghasilkan salinan obj yang dangkal—variabel instan dari obj disalin, tetapi bukan objek yang dirujuknya.

class X
  def initialize
    @y = [1,2,3,4]
  end
  attr_reader :y
end

class Z
  def self.change(arr)
    arr2 = arr.clone
    arr2[1] = 0
    arr2[2] = 0
    return arr2
  end
end

x = X.new
z = Z.change(x.y)
p z
p x.y
0
darkash 15 Januari 2021, 08:50

Namun, mengingat blok kode di bawah ini, hasil akhirnya tidak seperti yang saya maksudkan dan variabel instan benar-benar berubah dari luar kelas.

Tidak. Objek yang telah diubah oleh variabel instan referensi. Itulah yang diharapkan: array dapat diubah, dan Anda menyerahkan array kepada pemanggil, sehingga penelepon dapat dengan jelas mengubah array.

Tetapi variabel instan tidak diubah: masih menunjuk ke objek yang sama persis seperti sebelumnya.

Bos saya dan ibu saya memanggil saya dengan nama yang berbeda. Tetapi jika saya mencukur jenggot saya, keduanya akan melihat wajah saya yang dicukur bersih.

Memahami perbedaan antara benda dan nama benda itu mendasar dalam pemrograman.

Apa cara terbaik di mana saya bisa membaca nilainya dan mengembalikan perubahan yang diinginkan ke variabel lain alih-alih menimpa variabel instan itu sendiri?

Cara terbaik adalah tidak mengekspos representasi internal di tempat pertama. Tidak jelas dari pertanyaan Anda bagaimana klien diharapkan menggunakan X (penamaannya sangat buruk). Jadi, misalnya, jika klien diharapkan untuk mengulangi konten @y, maka Anda menawarkan mereka cara untuk melakukan hal itu dan hanya.

class X
  def initialize
    self.y = [1, 2, 3, 4]
  end

  def each_y(...)
    return enum_for(__callee__) unless block_given?
    y.each(...)
    self
  end

  private attr_accessor :y
end

Lihat Mengganti metode << untuk variabel instan untuk contoh lain dari masalah yang sama dan cara mengatasinya.

1
Jörg W Mittag 15 Januari 2021, 10:56