Mari kita lihat contoh bagaimana kita akan mencapai warisan dalam ES5
class Animal { constructor(name, energy) { this.name = name this.energy = energy } eat(amount) { console.log(`${this.name} is eating.`) this.energy += amount } sleep(length) { console.log(`${this.name} is sleeping.`) this.energy += length } play(length) { console.log(`${this.name} is playing.`) this.energy -= length } } class Dog extends Animal { constructor(name, energy, breed) { super(name, energy) this.breed = breed } bark() { console.log('Woof Woof!') this.energy -= .1 } } class Cat extends Animal { constructor(name, energy, declawed) { super(name, energy) this.declawed = declawed } meow() { console.log('Meow!') this.energy -= .1 } }
Kita boleh memvisualisasikan hierarki seperti ini:
Animal name energy eat() sleep() play() Dog breed bark() Cat declawed meow()
Katakan kemudian, anda ditugaskan untuk menambah entiti lain pada sistem: Pengguna.
User email username pets friends adopt() befriend() Animal name energy eat() sleep() play() Dog breed bark() Cat declawed meow()
Semuanya berfungsi dengan baik & menarik sehingga kini. Walau bagaimanapun, pengurus projek anda kini memberitahu anda untuk menambah keupayaan makan, tidur & bermain kepada Pengguna juga. Bagaimana anda akan melakukannya? Begini cara kami menangani perkara ini dalam OOP:
Mammal name eat() sleep() play() User email username pets friends adopt() befriend() Animal energy Dog breed bark() Cat declawed meow()
Ini kelihatan agak rapuh kerana entiti lain terpaksa diperkenalkan yang kini akan mempunyai kepentingannya sendiri apabila program ini berkembang. Anti-corak ini popular dipanggil God Object. Oleh itu, masalah dengan OOP ialah entiti mempunyai makna apabila anda menulisnya yang boleh diubah kemudian apabila keperluan berubah. Perubahan ini boleh meruntuhkan struktur hierarki kelas.
Saya rasa kekurangan kebolehgunaan semula datang dalam bahasa berorientasikan objek, bukan dalam bahasa berfungsi. Kerana masalah dengan bahasa berorientasikan objek ialah mereka mempunyai semua persekitaran tersirat yang mereka bawa bersama mereka. Anda mahukan pisang tetapi yang anda dapat ialah seekor gorila yang memegang pisang dan seluruh hutan.
-- Joe Armstrong (Pencipta Erlang)
Daripada memikirkan perkara apa, mari beralih kepada perkara yang dilakukan.
Daripada mempunyai kaedah ini digabungkan dengan rapat ke kelas, kita boleh menjadikannya sebagai fungsi dan menyusunnya bersama-sama pada bila-bila masa yang kita perlukan. Hebat! Tetapi bagaimana kita beroperasi pada contoh tertentu kemudian? Nah, kami menyampaikan contoh terus ke fungsi kami. Penutupan membolehkan fungsi mengingati keadaan(contoh) yang telah diluluskan.
const eater = (state) => ({ eat(amount) { console.log(`${state.name} is eating.`) state.energy += amount } }) const sleeper = (state) => ({ sleep(length) { console.log(`${state.name} is sleeping.`) state.energy += length } }) const player = (state) => ({ play(length) { console.log(`${state.name} is eating.`) state.energy -= length } }) const barker = (state) => ({ bark(length) { console.log(`Woof Woof!`) state.energy -= .1 } }) const meower = (state) => ({ meow(length) { console.log(`Meow!`) state.energy -= .1 } })
Contoh Anjing menjadi tidur, pemakan, pemain & menyalak:
function Dog(name, energy, breed) { let dog = { name, energy, breed } return Object.assign( dog, eater(dog), sleeper(dog), player(dog), barker(dog) ) } const dog = Dog('Dog', 10, 'Bulldog') dog.eat(10) dog.bark()
Kini pengguna juga boleh makan, tidur & bermain:
function User(email, username) { let user = { email, username, pets: [], friends: [] } return Object.assign( user, eater(user), sleeper(user), player(user) ) }
Tahniah, anda telah membebaskan diri anda daripada struktur pewarisan yang berganding rapat.
Atas ialah kandungan terperinci Warisan vs Komposisi. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!