먼저 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 } }
다음과 같이 계층 구조를 시각화할 수 있습니다.
Animal name energy eat() sleep() play() Dog breed bark() Cat declawed meow()
나중에 시스템에 또 다른 엔터티인 사용자를 추가하는 임무를 맡게 되었다고 가정해 보겠습니다.
User email username pets friends adopt() befriend() Animal name energy eat() sleep() play() Dog breed bark() Cat declawed meow()
지금까지는 모든 것이 잘 작동하고 멋집니다. 그러나 프로젝트 관리자는 이제 User에게 먹고, 자고, 놀 수 있는 기능도 추가하라고 지시합니다. 어떻게 하시겠습니까? OOP에서 이 문제를 해결하는 방법은 다음과 같습니다.
Mammal name eat() sleep() play() User email username pets friends adopt() befriend() Animal energy Dog breed bark() Cat declawed meow()
이제 프로그램이 성장함에 따라 고유한 의미를 갖게 될 또 다른 엔터티를 도입해야 했기 때문에 이는 매우 취약해 보입니다. 이 안티패턴은 일반적으로 God Object라고 불립니다. 따라서 OOP의 문제점은 엔터티를 작성할 때 나중에 요구 사항이 변경됨에 따라 변경될 수 있는 의미를 갖는다는 것입니다. 이러한 변화는 클래스 계층 구조를 무너뜨릴 수 있습니다.
재사용성 부족은 기능적 언어가 아닌 객체 지향 언어에서 발생한다고 생각합니다. 객체지향 언어의 문제점은 그들이 가지고 다니는 암시적 환경을 모두 가지고 있다는 것입니다. 바나나를 원했는데 얻은 것은 바나나를 안고 있는 고릴라와 정글 전체였습니다.
-- 조 암스트롱(Erlang 창시자)
무엇이 무엇인지 생각하기보다는, 무엇을 하는지로 옮겨봅시다.
이러한 메서드를 클래스에 긴밀하게 결합하는 대신 함수로 사용하고 필요할 때마다 함께 구성할 수 있습니다. 엄청난! 그러면 특정 인스턴스에서 어떻게 작업합니까? 글쎄, 우리는 인스턴스를 함수에 직접 전달합니다. 클로저를 사용하면 함수가 전달된 상태(인스턴스)를 기억할 수 있습니다.
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 } })
잠자고, 먹고, 놀고, 짖는 개의 예:
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()
이제 사용자는 먹고, 자고, 놀 수 있습니다.
function User(email, username) { let user = { email, username, pets: [], friends: [] } return Object.assign( user, eater(user), sleeper(user), player(user) ) }
축하합니다. 긴밀하게 결합된 상속 구조에서 해방되었습니다.
위 내용은 상속과 구성의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!