[javascript] 프로토 타입 기반 대 클래스 기반 상속

JavaScript에서 모든 객체는 동시에 인스턴스와 클래스입니다. 상속을 위해 모든 객체 인스턴스를 프로토 타입으로 사용할 수 있습니다.

파이썬, C ++ 등에서는 별도의 개념으로 클래스와 인스턴스가 있습니다. 상속을 수행하려면 기본 클래스를 사용하여 새 클래스를 작성해야하며,이를 사용하여 파생 인스턴스를 생성 할 수 있습니다.

JavaScript가 왜이 방향으로 진행 되었습니까 (프로토 타입 기반 객체 방향)? 기존의 클래스 기반 OO와 관련하여 프로토 타입 기반 OO의 장점과 단점은 무엇입니까?



답변

여기에는 약 100 가지의 용어 문제가 있으며, 대부분 자신의 아이디어를 ‘최고’처럼 들리려고하는 사람을 중심으로 구축되었습니다.

모든 객체 지향 언어는 몇 가지 개념을 처리 할 수 ​​있어야합니다.

  1. 특히 데이터 멤버 및 멤버 함수 또는 데이터 및 방법으로 알려진 데이터에 대한 관련 작업과 함께 데이터를 캡슐화합니다.
  2. 상속, 이러한 객체가 이러한 변경을 제외하고 다른 객체 세트와 같다고 말할 수있는 능력
  3. 다형성 ( “다양한 형태”) : 객체가 어떤 메소드를 실행할 것인지 스스로 결정하므로 언어에 따라 요청을 올바르게 라우팅 할 수 있습니다.

이제 비교하자면 다음과 같습니다.

첫 번째는 전체 “클래스”대 “시제품”질문입니다. 이 아이디어는 원래 Simula에서 시작되었으며, 클래스 기반 방법으로 각 클래스는 동일한 상태 공간 ( “가능한 값”을 읽음)과 동일한 작업을 공유하여 동등 클래스를 형성하는 일련의 객체를 나타 냈습니다. Smalltalk를 다시 살펴보면 클래스를 열고 메소드를 추가 할 수 있기 때문에 Javascript에서 수행 할 수있는 것과 사실상 동일합니다.

이후의 OO 언어는 정적 유형 검사를 사용할 수 있기를 원했기 때문에 컴파일 타임에 고정 클래스 세트라는 개념을 얻었습니다. 오픈 클래스 버전에서는 더 많은 유연성이있었습니다. 최신 버전에서는 컴파일러에서 테스트가 필요한 몇 가지 정확성을 검사 할 수있었습니다.

“클래스 기반”언어에서 해당 복사는 컴파일 타임에 발생합니다. 프로토 타입 언어에서 작업은 프로토 타입 데이터 구조에 저장되며 런타임시 복사 및 수정됩니다. 그러나 추상적으로 클래스는 여전히 동일한 상태 공간 및 메소드를 공유하는 모든 오브젝트의 동등 클래스입니다. 프로토 타입에 메소드를 추가하면 새로운 동등성 클래스의 요소를 효과적으로 만들 수 있습니다.

왜 그렇게합니까? 주로 런타임에 단순하고 논리적이며 우아한 메커니즘을 만들기 때문입니다. 이제, 새로운 객체를 만들 거나 새로운 클래스를 만들려면, 당신은 단순히 데이터와 프로토 타입의 데이터 구조를 모두 복사 깊은 복사를 수행해야합니다. 상속과 다형성은 어느 정도 무료로 제공됩니다. 메소드 조회는 항상 이름별로 메소드 구현을위한 사전을 요청하는 것으로 구성됩니다.

Javascript / ECMA 스크립트로 끝나는 이유는 기본적으로 10 년 전에 시작했을 때 훨씬 덜 강력한 컴퓨터와 훨씬 덜 정교한 브라우저를 다루고 있었기 때문입니다. 프로토 타입 기반 방법을 선택하면 원하는 객체 방향 속성을 유지하면서 인터프리터가 매우 간단 할 수 있습니다.


답변

프로토 타입 기반 접근 방식에 약간 편향된 비교는 Self : The Simplicity 의 논문에서 찾을 수 있습니다 . 이 논문은 프로토 타입을 위해 다음과 같은 주장을한다.

복사하여 작성 . 프로토 타입에서 새로운 객체를 생성하는 것은 간단한 생물학적 은유 복제와 함께 간단한 조작, 복사로 이루어집니다. 클래스에서 새 객체를 생성하는 것은 인스턴스화를 통해 이루어지며 여기에는 클래스의 형식 정보 해석이 포함됩니다. 인스턴스화는 계획에서 집을 짓는 것과 비슷합니다. 복사는 인스턴스화보다 단순한 은유로 우리에게 호소합니다.

기존 모듈의 예 . 프로토 타입은 형식과 초기화에 대한 설명이 아니라 객체의 예이므로 클래스보다 더 구체적입니다. 이 예제는 사용자가 이해하기 쉽도록 모듈을 재사용하는 데 도움이 될 수 있습니다. 프로토 타입 기반 시스템을 통해 사용자는 설명을 이해하도록 요구하지 않고 일반적인 담당자를 조사 할 수 있습니다.

독특한 객체 지원 . 자체는 고유 한 동작을 가진 고유 한 객체를 쉽게 포함 할 수있는 프레임 워크를 제공합니다. 각 객체에는 이름이 지정된 슬롯이 있고 슬롯은 상태 또는 동작을 보유 할 수 있으므로 모든 객체는 고유 한 슬롯 또는 동작을 가질 수 있습니다. 클래스 기반 시스템은 동일한 동작을 가진 많은 객체가있는 상황을 위해 설계되었습니다. 객체가 자신의 고유 한 행동을 갖도록 언어 적으로 지원하는 것은 없으며, 싱글턴 패턴을 생각하는 인스턴스가 하나만 보장되는 클래스를 만드는 것은 어색합니다 . 자아는 이러한 단점 중 어느 것도 겪지 않습니다. 모든 객체는 자체 동작으로 사용자 정의 할 수 있습니다. 고유 한 개체는 고유 한 동작을 보유 할 수 있으며 별도의 “인스턴스”가 필요하지 않습니다.

메타 회귀 제거 . 클래스 기반 시스템의 어떤 개체도 자급 자족 할 수 없습니다. 구조와 동작을 표현하기 위해서는 다른 객체 (클래스)가 필요합니다. 이것은 개념적으로 무한한 메타 회귀로 이어진다 : a point는 class Point의 인스턴스이며 Point, 이것은 metametaclass의 인스턴스 인 Pointad infinitum 인 metaclass 의 인스턴스이다
. 반면, 프로토 타입 기반 시스템에서 객체는 자체 동작을 포함 할 수 있습니다. 생명을 불어 넣는 데 다른 물체가 필요하지 않습니다. 프로토 타입은 메타 회귀를 제거합니다.

Self 는 아마도 프로토 타입을 구현 한 최초의 언어 일 것입니다 (JIT와 같은 다른 흥미로운 기술을 개척하여 나중에 JVM에 도입했습니다). 따라서 다른 Self 논문 도 읽는 것이 유익해야합니다.


답변

Douglas Crockford의 JavaScript 에 대한 훌륭한 책을 확인해야합니다 . JavaScript 작성자가 내린 일부 디자인 결정에 대해 아주 잘 설명합니다.

JavaScript의 중요한 디자인 측면 중 하나는 프로토 타입 상속 시스템입니다. 객체는 JavaScript에서 일류 시민이므로 일반 함수도 객체 ( ‘Function’객체는 정확함)로 구현됩니다. 제 생각에는 브라우저 내부에서 실행되도록 설계되었을 때 많은 단일 객체를 만드는 데 사용되었습니다. 브라우저 DOM에는 해당 창, 문서 등 모든 단일 객체가 있습니다. 또한 JavaScript는 느슨하게 형식화 된 동적 언어 (강력한 형식의 Python과 달리 동적 언어)와 달리 ‘prototype’속성을 사용하여 객체 확장 개념을 구현했습니다.

따라서 JavaScript로 구현 된 프로토 타입 기반 OO에 대한 전문가가 있다고 생각합니다.

  1. 느슨한 유형의 환경에 적합하며 명시 적 유형을 정의 할 필요가 없습니다.
  2. 싱글 톤 패턴을 구현하기가 엄청나게 쉽습니다 (이 점에서 JavaScript와 Java를 비교하면 내가 무엇을 말하는지 알게됩니다).
  3. 다른 객체의 컨텍스트에서 객체의 메소드를 적용하고 객체 등에서 동적으로 메소드를 추가 및 교체하는 방법을 제공합니다 (강력한 언어로는 불가능한 것).

프로토 타입 OO의 단점은 다음과 같습니다.

  1. 개인 변수를 구현하는 쉬운 방법은 없습니다. 클로저를 사용하여 Crockford 의 마법사를 사용 하여 개인 변수를 구현할 수 있지만 Java 또는 C #과 같은 개인 변수를 사용하는 것만 큼 간단하지는 않습니다.
  2. 아직 JavaScript로 여러 상속 (그 가치에 따라)을 구현하는 방법을 모르겠습니다.

답변