class 키워드없이 "객체 지향"프로그래밍을 구현할 수 있습니까?


29

은행에서 "계정"을 추상화하고 싶다고 가정 해 봅시다. 다음 function은 파이썬 에서 객체를 사용하는 한 가지 방법입니다 .

def account():
    """Return a dispatch dictionary representing a bank account.

    >>> a = account()
    >>> a['deposit'](100)
    100
    >>> a['withdraw'](90)
    10
    >>> a['withdraw'](90)
    'Insufficient funds'
    >>> a['balance']
    10
    """
    def withdraw(amount):
        if amount > dispatch['balance']:
            return 'Insufficient funds'
        dispatch['balance'] -= amount
        return dispatch['balance']
    def deposit(amount):
        dispatch['balance'] += amount
        return dispatch['balance']
    dispatch = {'balance': 0,
                'withdraw': withdraw,
                'deposit': deposit}
    return dispatch

다음은 타입 추상화를 사용하는 또 다른 방법입니다 (예 class: Python의 키워드).

class Account(object):
    """A bank account has a balance and an account holder.

    >>> a = Account('John')
    >>> a.deposit(100)
    100
    >>> a.withdraw(90)
    10
    >>> a.withdraw(90)
    'Insufficient funds'
    >>> a.balance
    10
    """



    def __init__(self, account_holder):
        self.balance = 0
        self.holder = account_holder

    def deposit(self, amount):
        """Add amount to balance."""
        self.balance = self.balance + amount
        return self.balance

    def withdraw(self, amount):
        """Subtract amount from balance if funds are available."""
        if amount > self.balance:
            return 'Insufficient funds'
        self.balance = self.balance - amount
        return self.balance

선생님은 class키워드 를 소개하고 다음과 같은 요점을 보여줌으로써 "객체 지향 프로그래밍"이라는 주제를 시작했습니다 .

객체 지향 프로그래밍

모듈 식 프로그램을 구성하는 방법 :

  • 추상화 장벽
  • 메시지 전달
  • 정보와 관련 행동 묶기

위의 정의를 만족시키기 위해 첫 번째 방법으로 충분하다고 생각하십니까? 그렇다면 왜 class객체 지향 프로그래밍을하기 위해 키워드가 필요한가?


2
다행입니다. =) 필자는 파이썬을 잘 알지 못하지만 철저한 답변을 줄 수는 있지만 Javascript에서 OOP를 수행하는 일반적인 방법은 설명하는 "함수 객체"와 유사하다는 것을 알고 싶습니다. 모든 객체에 대해 각 메소드의 별도 사본을 사용하는 대신 객체가 메소드를 "공유"할 수 있습니다. 파이썬도 class비슷한 최적화를 수행합니다.
Ixrec

자세한 답변을 원한다면 다른 질문을하거나 채팅방에 참여해야하지만 짧은 대답은 기본적으로 사실입니다 (프로토 타입 상속, 배열 등을 완전히 무시하는 경우). 대부분의 JS 객체는 문자열 키를 임의의 값으로 만 나눈 것입니다. foo.bar()일반적으로와 동일하며 foo['bar']()드문 경우에 후자의 구문이 실제로 유용합니다.
Ixrec 10


8
이것은 OOP에 대한 기본적인 이해로가는 길에 정말 중요한 질문입니다. 관심이 있으시면 언어의 OOP 부분에 의존하지 않고 JavaScript로 간단한 객체 시스템을 만드는 블로그 게시물을 읽을 수 있습니다. 첫 번째 예제에는 중요한 단점이 있습니다. 작성하는 곳 object['method'](args)에서 Python 객체는 실제로 object['method'](object, args). 이는 기본 클래스가 하위 클래스 (예 : 전략 패턴)에서 메소드를 호출 할 때 적합합니다.
amon

13
다른 사람들이 지적했듯이, 이것은 OOP에 대한 지각적인 질문입니다. 그러나이 기회를 통해 실제 은행이 은행 계좌를 나타내는 방식이 아님을 알 수 있습니다. 은행은 변경 및 "신용"할 때 변경되는 변경 가능한 "계정"개체가 없습니다. 쓰기 전용 트랜잭션 목록이 있고 트랜잭션 목록에서 잔액을 계산합니다. 좋은 연습으로 다양한 언어로 해당 메커니즘을 구현해보십시오.
Eric Lippert

답변:


66

축하합니다! 특정 프로그래밍 언어 지원없이 객체 방향을 수행 할 수 있다는 잘 알려진 사실을 재발견했습니다. 기본적 으로이 고전적인 교과서 에서 Scheme에 객체가 도입되는 것과 같은 방식 입니다 . Scheme에는 class키워드 또는 이와 동등한 종류가 없으며 클래스를 사용하지 않고도 객체를 만들 수 있습니다.

그러나 객체 지향 패러다임은 매우 성공적이어서 많은 언어 (파이썬도 예외는 아님)가이를 기본적으로 지원합니다. 이는 개발자가 패러다임을 쉽게 사용하고 해당 언어에 대한 표준 객체 지향 형식을 제공하기위한 것입니다. 그것은 본질적으로 언어의 많은이 제공하는 이유 같은 이유는 for그것이 사용하여 에뮬레이션 할 수 있지만, 루프를 while단순히 - 코드의 하나 또는 두 개의 추가 선 루프를 사용의 용이성 .


"해당 언어에 대한 표준 형태의 객체 지향을 제공하기 위해"거기에 JavaScript에 대한 비판이 들립니까? ;)
jpmc26

1
@ jpmc26 : 의도적으로 아닙니다. 그리고 JavaScript로 객체를 생성하는 방법에는 널리 인정되는 표준이있는 것 같습니다.
Doc Brown

@overexchange : 질문이 있습니까?
Doc Brown

1
@overexchange : OOP가 의미하는 바는 논쟁의 여지가 있지만 다른 생각의 학교가 있지만 SICP 정의는 질문의 세 가지 핵심 요점에서 거의 동일합니다. 추상화 구축에 관한 것이지만 포인트 2와 3을 잊지 마십시오. 예, OOP 개념은 "상태 변경"을 포함하지만 "불변 객체"(Java 또는 C #의 문자열 클래스, Python과 같은) 개념도 허용합니다 일부 변경 가능하고 일부 변경 불가능한 데이터 유형도 있습니다). 그리고 질문의 첫 번째 예는 두 번째 예뿐만 아니라 그 정의를 확인합니다.
Doc Brown

2
@overexchange : 이것은 Alain Kay의 객체 지향 (작은 대화 언어의 발명가)에 대한 정의로 돌아갑니다. 이 stackoverflow.com/questions/2347973/… 이전 SO 기사 에서 포괄적 인 답변을 찾을 수 있습니다. SICP 의미에서 IMHO "개체 간 메시지 전달"은 단지 "정의 된 통신 프로토콜"을 통해서만 개체의 내부 데이터에 직접 액세스하지 않음을 의미합니다. 파이썬과 같은 OO 언어에서 이것은 단지 "객체의 메소드 호출"을 의미 할 수 있습니다.
Doc Brown

13

첫 번째 정의가 선생님이 세 가지 점을 만족 시킨다는 데 동의합니다. 클래스 키워드 가 필요 하다고 생각하지 않습니다 . 표지 아래에 다른 유형의 데이터와 데이터를 처리하는 함수가있는 데이터 구조 외에 다른 개체는 무엇입니까? 물론 기능도 데이터입니다.

더 나아가서 객체 지향 프로그래밍을하는 것이 언어가 제공 하는 키워드 에 크게 의존하지 않는다고 말하면 원하는 경우 C로 객체 지향 프로그래밍을 수행 할 수 있습니다! 실제로 리눅스 커널 은 그러한 기술을 사용합니다.

여기서 class 키워드에서 유추 할 수있는 것은 언어가 이러한 종류의 구성을 기본적으로 지원하며 모든 후프를 통해 기능을 직접 구현할 필요는 없다는 것입니다. 그 자체!). 당신이 얻을 수있는 모든 구문 설탕은 말할 것도 없습니다.


상속은 어떻습니까? 하위 유형 / 수퍼 유형에 대해 실시간으로 중요합니까? 내 첫 번째 접근법은 이것을 즐겁게하지 않을 수 있습니다!
overexchange

5
OOP에는 상속이 필요하지 않습니다. 첫 번째 예제에서도 상속을 구현할 수 있습니다. 이주는 매우 "깨끗한"것이 아니라 가능한 한 동일합니다.
Zavior

3
@Zavior 그 의견은 VB6을 생각 나게합니다. 상속없는 객체 지향은 실제로 코드를 덜 깔끔하게 만들어줍니다.
RubberDuck

1
@overexchange 당신이 그것에 대해 생각할 때, 상속은 클래스간에 공통 코드 / 동작을 공유하는 것입니다. 그 코드를 항상 반복하는 것을 막는 것은 없습니다. 그래도 유지하기가 끔찍할 것입니다. 상속이 존재하는 이유가 있습니다 :)
Zavior

1
@Zavior 가장 기본적인 형태 인 "서브 클래 싱"은 "여기서 내가 정의하고있는 상위 디스패치 및 데이터 실행 기능을 반환하기 전에"클래스 "인 ha ha를 나타내는 추상화입니다. ha), ThisParentFoo가 참조하는 '슈퍼 클래스'디스패치 및 데이터 실행 기능을 인스턴스화합니다. " 그게 전부입니다. 순전 한 다중 상속에 관해서는 여전히 모든 것이지만 "다이아몬드 문제"를 도입해야한다는 경고가 있으므로 다중 상속이 짜증납니다.
zxq9

9

물론 당신은 할 수!

자체 프로그래밍 언어는 모든 것이 객체이고 클래스 나 그 밖의 어떤 것도없는 동적 프로토 타입 기반 객체 지향 언어입니다. 프로토 타입 객체와 객체를 생성하는 방법에 대한 템플릿으로 클래스를 사용하는 대신 복제하는 아이디어에 중점을 둡니다.

자세한 내용 은 http://www.selflanguage.org/ 를 확인 하십시오 . 나는 그것이 매우 흥미 롭다고 생각하며 OOP를 좋아한다면 일반적이지 않은 것을 확인하는 것이 좋습니다.


0

항상 그런 것은 아닙니다 : 언어에 따라 다릅니다. 파이썬 에서이 작업을 수행 할 수있는 능력을 입증했지만 (귀하의 질문이 파이썬 태그에도 불구하고 언어에 무관심한 경우) 모든 언어가 이것을 할 수있는 것은 아닙니다. 예를 들어 Java는 대부분 할 수 없습니다. main을 포함하는 클래스를 무시하면 class 키워드없이 main 내에 정의 된 객체에서 임의의 메소드 / 필드를 정의 할 수있는 방법이 없습니다. 익명 클래스는 존재하지만 인터페이스가 필요하며 인터페이스에 정의 된 멤버를 제외한 공용 멤버를 가질 수 없습니다. 커스텀 인터페이스를 정의한 후 익명 클래스를 만들 수는 있지만, 단순히 클래스를 사용하는 것과 동일하지만 덜 편리합니다.

Doc Brown은 큰 답을 가지고 있지만 내가하려고하는 요점은 귀하의 솔루션을 전혀 허용하지 않는 언어가 적어도 하나 이상 있다는 것입니다.


초보자는 "객체 지향 프로그래밍"개념을 배우기 위해 언어에 구애받지 않고 있습니다. "Doc Brown"은 같은 줄에 답을했다고 생각합니다. 그는 sicp text-chap3를 읽었습니다.
overexchange

내 대답의 유효성을 검사하기 위해 클래스를 사용해야하는 언어의 이름을 지정하고 싶습니다. 그러나 나는 몇 가지 언어 만 알고 있으며 아아 Java는 해결 방법을 허용합니다. C ++에는 구조체가 있으며 Javascript flat out은 시연 한 것을 허용합니다. 스몰 토크와 에펠은 엄격하게 구성되어 있다고 들었 기 때문에 수업이 필요할지도 모른다고 생각합니다.
SkySpiral7

Doc Brown과 같이 체계를 사용하여 oop을 배우면이 질문을하지 않았을 것입니다. 불행히도, 내가 배우고있는 SICP 과정의 버전은 파이썬을 사용합니다.
overexchange

1
모든 유효한 Java 프로그램에는 class키워드 가 포함되어 있어야합니다 . 그러나 Java 객체 시스템 위에 자체 객체 시스템을 구현할 수는 있지만 왜 그런 일을하고 싶은지 모르겠습니다.
브라이언 고든

1. Java는 커스텀 데이터 구조를 만드는 데 사용될 수있는 다른 모든 키워드를 단순히 버렸기 때문에이 점에서 정말 특별합니다. 내가 아는 거의 모든 언어에는 기록이나 폐쇄가 있습니다. 2. 자바에서도 배열로 구축 된 메모리에서 프로그래밍 할 수 있습니다 . 그리고 당신은 할 수 사용하여, 그 내에서 객체 지향을 구현하는 class언어가 클래스에 기능을 넣을 것을 요구 때문 키워드를. 물론 이것은 매우 이론적이지만 Java에서도 내장 클래스없이 객체 지향을 수행 할 수 있습니다!
cmaster

0

교사의 정의는 가장 유용하고 독창적 인 객체 지향 프로그래밍의 요점을 완전히 놓치지 않습니다. "메시지 전달"은 스몰 토크 사람들이 꿈꾸는 말도 안되는 일이며 시도 된 모든 곳에서 실패했습니다. OOP의 진정한 힘은 Liskov 대체로 알려져 있으며, 개념을 설명하고 이해하는 것은 매우 간단하지만 기본 구현은 언어 수준의 지원 없이는 제대로 수행 할 수 없을 정도로 복잡합니다.

Liskov 대체의 아이디어는 코드가 특정 유형의 변수를 기대하는 모든 위치에서 해당 유형에서 파생 된 모든 유형을 허용 할 수 있으며 파생 된 유형의 세부 사항에 대한 지식이 없어도 여전히 올바르게 작동한다는 것입니다.

예를 들어, GUI 프레임 워크는 모든 곳에서 Liskov 대체를 사용합니다. Control"모든 컨트롤"을 표현할 수 있는 기본 클래스를 사용 하는 경향이 있습니다.이 클래스는 그리기, 크기 조정 및 사용자 입력에 대한 응답과 같은 기본 동작에 대해 알고있는 인터페이스를 정의합니다. 컨트롤을 클릭하면 UI 프레임 워크는 Click컨트롤의 종류를 신경 쓰지 않고 컨트롤 에서 메서드를 호출 한 다음 컨트롤이 자체 클래스에 적합한 방식으로 클릭을 처리하도록합니다. Button제어는보다 클릭했을 때 완전히 다른 뭔가해야 할 TextBox하나의 예를 제공하기 위해, 제어.

예, 위에서 설명한 중첩 함수 트릭을 사용하여 객체와 비슷한 것을 만들 수는 있지만 상속과 Liskov 대체를 얻을 수 없기 때문에 진정한 OOP를 대체하는 극히 제한적인 것입니다.


C 언어에서 'struct parent {}'와 'struct child {struct parent * ptr;}'를 말할 수 없습니까? 이것이 비 oop 언어 구문에서 상속되지 않습니까?
overexchange

@overexchange : 그것은 가짜를 시도하는 비 OO 시도이지만, 컴파일러는 당신을 다른 것으로 대체 할 수 없습니다 . ( 적어도 타입 캐스트가 없으면 인수로 사용하는 child*함수 에는 a 를 전달할 수 없습니다 parent*.) 더 나쁜 것은 C 구조체에는 바인딩 된 메서드를 가질 수 없으며 가상 메서드 는 지원하지 않는 것입니다. Liskov 대체의 마술을 작동시키는 이유는 VMT를 수동으로 구성해야하기 때문입니다.
메이슨 휠러

1
Linux 커널은 여러 가지 OO 기술의 에뮬레이션을 사용하며, 언어 지원없이 모두 수동으로 코딩해야합니다. 이것은 리눅스에 대한 리누스의 법칙의 자유로운 적용에 의해 균형을 잡는 버그에 대한 많은 기회를 가져온다. 그렇습니다. 동등성을 보장하는 것이 가능합니다.하지만 언어 지원 없이는 제대로 이해하기가 매우 어렵다는 것이 나의 견해입니다. 또한 왜 파이썬에 관한 질문 일 때 C에 대한 이러한 모든 질문이 있습니까? C에서는 중첩 함수 트릭을 처음부터 수행 할 수 없습니다.
메이슨 휠러

1
@overexchange Java는 언제부터 "프로그래머 천국"입니까?
Brandin

1
"메시지"가 "기능 호출"과 다른 것을 의미하는 스몰 토크, Erlang 또는 Java 스타일 OOP 시스템에서는 메시지 전달이 실패 하지 않았습니다 ( "메시지"라는 용어를 사용하는 스레드 안전 대기열 VS Qt의 신호 및 슬롯) "방법 호출"을 의미 할 때). 메시지! = 함수 호출. 진정한 메시징은 성공적 일뿐만 아니라 대량의 동시적이고 강력한 시스템을 작성하는 유일한 방법 인 것으로 보입니다. 이것은 'class'키워드없이 Java 스타일 OOP를 구현하는 것과 직교합니다. 그것은 수 있습니다 할 수. 항상 유용한 것은 아닙니다 . 메시징은 요점 옆에 있습니다.
zxq9

-1

빠른 답변

예, 프로그래머는 "클래스"없이 객체 지향 프로그래밍을 적용 할 수 있습니다.

긴 지루한 광범위한 설명 답변

많은 프로그래머들이 생각하는 첫 번째 개념은 "클래스"입니다.

예, 프로그래머는 "클래스"없이 객체 지향 프로그래밍을 적용 할 수 있지만 각 프로그래밍 언어의 기능과 제한으로 제한됩니다.

귀하의 게시물은 Python 으로 태그되어 있으므로 질문 제목은 "Python에서 클래스없이 객체 지향 프로그래밍을 구현하는 방법"과 유사 할 수 있습니다.

저는 현재 "Object and Class Oriented Programming"문구를 사용하여 Javascript의 "Prototyping"또는 Visual Basic "Based"와 같은 다른 변형이나 "functors"를 사용하여 "Pure C"의 에뮬레이션을 식별합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.