클래스 기반 OOP에 비해 프로토 타입 기반 OOP의 장점은 무엇입니까? 적은 메모리

클래스 기반 언어와 관련하여 주로 OOP를 처리 한 후 Javascript 프로그래밍을 처음 시작했을 때 프로토 타입 기반 OOP가 클래스 기반 OOP보다 선호되는 이유에 대해 혼란스러워했습니다.

  1. 프로토 타입 기반 OOP를 사용하는 경우 구조적 이점은 무엇입니까? (예를 들어 특정 응용 프로그램에서 더 빠르거나 적은 메모리 집약적이라고 생각합니까?)
  2. 코더의 관점에서 장점은 무엇입니까? (예 : 프로토 타이핑을 사용하여 특정 응용 프로그램을 코딩하거나 다른 사람의 코드를 쉽게 확장 할 수 있습니까?)

이 질문을 특히 자바 스크립트에 대한 질문으로 보지 마십시오 (수년 동안 프로토 타입과는 전혀 관련이없는 많은 결함이있었습니다). 대신, 프로토 타이핑 대 클래스의 이론적 장점과 관련하여 살펴보십시오.

감사합니다.



답변

Java로 RPG 게임을 작성할 때 두 가지 접근 방식에 대해 많은 경험이 있습니다. 원래 클래스 기반 OOP를 사용하여 전체 게임을 작성했지만 결국 이것이 잘못된 접근 방식이라는 것을 깨달았습니다 (클래스 계층 구조가 확장됨에 따라 유지 관리가 불가능 해짐). 따라서 전체 코드베이스를 프로토 타입 기반 코드로 변환했습니다. 그 결과 관리 가 훨씬 쉬워졌습니다.

관심이 있다면 여기에 소스 코드 ( Tyrant-Java Roguelike )

주요 이점은 다음과 같습니다.

  • 새로운 “클래스”를 만드는 것은 사소한 일입니다 . 프로토 타입을 복사하고 몇 가지 속성과 새로운 클래스를 변경하면됩니다. 나는 이것을 사용하여 새로운 유형의 물약을 정의했다. 새로운 클래스 파일과 많은 상용구보다 훨씬 좋습니다!
  • 비교적 적은 코드로 매우 많은 수의 “클래스”를 구축하고 유지하는 것이 가능합니다. 예를 들어 Tyrant는 3000 개의 다른 프로토 타입과 같은 코드가 총 42,000 줄에 불과했습니다. Java에게는 정말 놀랍습니다!
  • 다중 상속은 쉽습니다. 한 프로토 타입에서 속성의 서브 세트를 복사하여 다른 프로토 타입의 속성에 붙여 넣기 만하면됩니다. 예를 들어, RPG에서 “스틸 골렘”에 “스틸 오브젝트”의 일부 속성과 “골렘”의 일부 속성 및 “지능없는 몬스터”의 일부 속성을 갖기를 원할 수 있습니다. 프로토 타입으로 쉽게 상속 상속 계층 구조로 시도해보십시오 …
  • 속성 수정자를 사용하여 영리한 작업을 수행 할 수 있습니다 . 일반 “읽기 속성”메서드에 영리한 논리를 사용하면 다양한 수정자를 구현할 수 있습니다. 예를 들어, 착용 한 사람에게 +2의 힘을 더한 매직 링을 쉽게 정의 할 수있었습니다. 이에 대한 논리 는 “읽기 강도”방법이 아닌 링 객체에 있었으므로 코드베이스의 다른 곳에 많은 조건부 테스트를 수행하지 않아도됩니다 (예 : “문자가 강도 링을 착용하고 있습니까?”).
  • 인스턴스는 다른 인스턴스의 템플릿이 될 수 있습니다. 예를 들어 객체를 “복제”하려는 경우 기존 객체를 새 객체의 프로토 타입으로 사용하면됩니다. 다른 클래스에 대해 복잡한 복제 로직을 많이 작성할 필요가 없습니다.
  • 런타임에 동작을 변경하는 것은 매우 쉽습니다. 즉, 속성을 변경하고 런타임에 객체를 거의 임의로 “모핑”할 수 있습니다. 게임 내에서 멋진 효과를 내고이를 “스크립트 언어”와 결합하면 런타임에 거의 모든 것이 가능합니다.
  • “기능적”스타일의 프로그래밍에 더 적합합니다 . 특정 클래스에 연결된 메서드의 내장 된 논리가 아니라 객체를 적절하게 분석하는 많은 함수를 작성하는 경향이 있습니다. 개인적으로이 FP 스타일을 선호합니다.

주요 단점은 다음과 같습니다.

  • 동적 객체 시스템을 효과적으로 생성하기 때문에 정적 타이핑에 대한 보장을 잃게됩니다 . 이것은 행동이 정확하고 객체가 올바른 “종류”인지 확인하기 위해 더 많은 테스트를 작성해야 함을 의미합니다.
  • 성능에 약간의 오버 헤드 가 있습니다. 일반적으로 객체 속성을 읽으려면 하나 이상의 맵 조회를 수행해야하므로 성능 측면에서 약간의 비용이 발생합니다. 제 경우에는 문제가되지 않았지만 어떤 경우에는 문제가 될 수 있습니다 (예 : 모든 프레임에서 많은 객체를 쿼리하는 3D FPS)
  • 리팩토링은 동일한 방식으로 작동하지 않습니다 . 프로토 타입 기반 시스템에서는 본질적으로 코드를 사용하여 상속 계층을 “빌딩”합니다. IDE / 리팩토링 도구는 접근 방식을 방해 할 수 없으므로 실제로 도움이되지 않습니다. 나는 이것이 문제를 발견하지 못했지만 조심하지 않으면 손을 could 수 있습니다. 상속 계층 구조가 올바르게 구성되어 있는지 테스트하기를 원할 것입니다!
  • 그것은 약간 외계인입니다 -기존의 OOP 스타일에 익숙한 사람들은 쉽게 혼란 스러울 수 있습니다. “”사물 “이라는 클래스가 하나만 있다는 것은 무엇을 의미합니까?!” – “이 마지막 Thing 클래스를 어떻게 확장합니까?!” – “당신은 OOP 원칙을 위반하고 있습니다 !!!” – “모든 종류의 객체에 작용하는 정적 함수를 모두 갖는 것은 잘못입니다!?!?”

마지막으로 일부 구현 노트 :

  • 속성에는 Java HashMap을 사용하고 프로토 타입에는 “부모”포인터를 사용했습니다. 이것은 잘 작동하지만 다음과 같은 단점이 있습니다. 조심하지 않으면 미묘한 버그가 발생할 수 있습니다!
  • 이 작업을 다시 수행하는 경우 속성 ( Clojure의 지속적 맵 과 같은 종류 ) 또는 자체 Java 지속적 해시 맵 구현에 대해 변경 불가능한 지속적 맵을 사용합니다 . 그러면 불변의 행동과 결합 된 저렴한 복사 / 변경의 이점을 얻을 수 있으며 객체를 부모와 영구적으로 연결할 필요가 없습니다.
  • 함수 / 메소드를 객체 속성에 포함 시키면 재미를 느낄 수 있습니다. Java 에서이 ( “스크립트”클래스의 익명 하위 유형)에 사용한 해킹은 그다지 우아하지 않았습니다.이 작업을 다시 수행하면 스크립트 (Clojure 또는 Groovy)에 쉽게 포함시킬 수있는 적절한 언어를 사용할 것입니다

답변

프로토 타입 기반 OOP의 주요 장점은 객체 및 “클래스”를 런타임에 확장 할 수 있다는 것입니다.

클래스 기반 OOP에는 불행히도 프로그래밍 언어에 따라 몇 가지 좋은 기능이 있습니다.

Object Pascal (Delphi), VB.Net & C #에는 속성 (필드와 혼동하지 말 것)과 속성 액세스 방법을 사용하는 매우 직접적인 방법이 있지만 Java & C ++ 속성은 메서드에 의해 액세스됩니다. 그리고 PHP에는 “매직 메소드”라고하는 두 가지가 혼합되어 있습니다.

기본 클래스 OO 언어에는 정적 타이핑이 있지만 일부 동적 타이핑 클래스가 있습니다. Class OO를 사용한 정적 타이핑은 매우 유용하다고 생각합니다. Object Introspection이라는 기능을 통해 IDE를 만들고 시각적으로 신속하게 웹 페이지를 개발할 수 있기 때문입니다.


답변

@umlcat에 동의해야합니다. 수업 확장은 큰 장점입니다. 예를 들어, 오랜 기간 동안 문자열 클래스에 더 많은 기능을 추가하려고한다고 가정하십시오. C ++에서는 이전 문자열 클래스 생성을 계속 상속하여이 작업을 수행합니다. 이 접근 방식의 문제점은 각 세대가 본질적으로 다른 유형의 고유 한 유형이되어 기존 코드 기반을 크게 다시 작성할 수 있다는 것입니다. 프로토 타입 상속을 사용하면 원래의 기본 클래스에 새로운 메소드를 단순히 ‘첨부’할 수 있습니다. 상속 된 클래스와 상속 관계를 어디서나 만들지 않아도됩니다. C ++이 새로운 표준에서 비슷한 확장 메커니즘을 제공하는 것을보고 싶습니다. 그러나 그들의위원회는 흥미롭고 인기있는 기능을 추가하려는 사람들이 운영하는 것 같습니다.