Mengapa mekanisme pewarisan Python memungkinkan saya mendefinisikan kelas yang tidak dapat dipakai dengan benar?

Saya minta maaf atas rumusan pertanyaan yang agak kabur. Saya akan mencoba memperjelas maksud saya melalui contoh sederhana di bawah ini. Saya memiliki kelas yang ingin saya gunakan sebagai basis untuk kelas lain:

class parent:
    def __init__(self, constant):
        self.constant = constant
    def addconstant(self, number):
        return self.constant + number

Parameter self.constant sangat penting untuk kegunaan kelas, karena metode addconstant bergantung padanya. Oleh karena itu, metode __init__ berupaya memaksa pengguna untuk menentukan nilai parameter ini. Sejauh ini bagus.

Sekarang, saya mendefinisikan kelas anak seperti ini:

class child(parent):
    def __init__(self):
        pass

Tidak ada yang menghentikan saya untuk membuat instance kelas ini, tetapi ketika saya mencoba menggunakan addconstant, jelas akan crash.

b = child()
b.addconstant(5)
AttributeError: 'child' object has no attribute 'constant'

Mengapa Python mengizinkan melakukan ini!? Saya merasa bahwa Python terlalu fleksibel dan entah bagaimana melanggar inti OOP dan enkapsulasi. Jika saya ingin memperluas suatu kelas untuk memanfaatkan warisan, saya harus berhati-hati dan mengetahui detail tertentu dari implementasi kelas tersebut. Dalam hal ini, saya harus tahu bahwa memaksa pengguna untuk menyetel konstanta parameter constant adalah hal mendasar agar tidak merusak kegunaan kelas. Bukankah ini melanggar prinsip enkapsulasi?


person Onturenio    schedule 19.02.2021    source sumber
comment
Python memberikan banyak tanggung jawab pada pengguna untuk menjadi "orang dewasa yang bertanggung jawab", misalnya. dengan atribut “pribadi” yang hampir tidak dilindungi dan semacamnya. Itu bukan untuk mengasuh Anda…   -  person deceze♦    schedule 19.02.2021
comment
Banyak alasan orang menyukai Python adalah karena ia sangat fleksibel dan tidak melarang banyak hal. Jadi kalau mau panggil parent initializer ya panggil saja, kalau tidak ya jangan.   -  person wim    schedule 19.02.2021
comment
Jika saya ingin memperluas suatu kelas untuk memanfaatkan warisan, saya harus berhati-hati dan mengetahui detail tertentu dari implementasi kelas tersebut dengan tepat!   -  person Cyttorak    schedule 19.02.2021
comment
Enkapsulasi lebih merupakan masalah Java, bukan untuk Python.   -  person M-Chen-3    schedule 19.02.2021
comment
Perhatikan juga bahwa definisi kelas itu sendiri tidak mendefinisikan atribut constant; menelepon parent.__init__ tidak.   -  person chepner    schedule 19.02.2021


Jawaban (1)


Karena Python adalah bahasa yang dinamis. Ia tidak mengetahui atribut apa yang ada pada instance parent sampai penginisialisasi parent menempatkannya di sana. Dengan kata lain, atribut parent ditentukan saat Anda membuat instance parent dan bukan sesaat sebelumnya.

Dalam bahasa seperti Java, atribut parent akan dibuat pada waktu kompilasi. Namun definisi kelas Python dieksekusi, bukan dikompilasi.

Dalam praktiknya, hal ini sebenarnya tidak menjadi masalah. Ya, jika Anda lupa memanggil penginisialisasi kelas induk, Anda akan mendapat masalah. Namun memanggil penginisialisasi kelas induk adalah sesuatu yang selalu Anda lakukan, dalam bahasa apa pun, karena Anda menginginkan perilaku kelas induk. Jadi, jangan lupa melakukan itu.

Teknik yang terkadang berguna adalah dengan mendefinisikan default yang masuk akal pada kelas itu sendiri.

class parent:
    constant = 0
    def __init__(self, constant):
        self.constant = constant
    def addconstant(self, number):
        return self.constant + number

Python kembali mengakses atribut kelas jika Anda belum mendefinisikannya pada sebuah instance. Jadi, ini akan memberikan nilai cadangan jika Anda lupa melakukannya.

person kindall    schedule 19.02.2021
comment
Saya berpendapat bahwa fallback default kelas hanya mengaburkan kesalahan. Sekarang Anda tidak akan melihat pesan kesalahan, tetapi mungkin akan berperilaku berbeda secara halus. - person deceze♦; 19.02.2021
comment
Tergantung pada kasus penggunaannya, tapi ya, saya dapat melihat favorit gagal dengan cepat di sini. - person kindall; 19.02.2021