오리 타이핑이란 무엇입니까?


429

온라인 소프트웨어에서 임의의 주제를 읽는 동안 오리 타이핑 이라는 용어를 발견했으며 완전히 이해하지 못했습니다.

"오리 타이핑"이란 무엇입니까?


1
@ 미치 나는 어떤 형태의 상속으로 시도하고 무언가를 얻었다. 그러나 많은 것을 따라갈 수 없었습니다. 내가 잘못된 질문을한다면 미안합니다.
sushil bharwani

3
@sushil bharwani : 아니오, 화 내지 마십시오. 그러나 사람들은 첫 번째 호출 포트 (즉, 첫 번째 작업)가 여기에 게시하기 전에 검색을 시도하는 것으로 기대합니다.
Mitch Wheat

104
위의 주장을 감안할 때, 실제로 생각할 수있는 거의 모든 질문에 대해 인터넷상의 어딘가에 대답 할 것이라고 확신하기 때문에 stackoverflow가 실제로 필요하지 않은 것 같습니다. 지식이 풍부한 친구. 많은 사람들이 스택 오버 플로우의 요점을 놓쳤다 고 생각합니다.
rhody

41
나는 SO가 "정식 질문의 저장소"가 될 수있는 곳을 읽었을 것이라고 확신하며, 당신은 이것보다 정식을 얻을 수 없다고 확신합니다.
heltonbiker

답변:


302

강력한 타이핑 이없는 동적 언어 에서 사용되는 용어 입니다.

아이디어는 객체에서 기존 메소드를 호출하기 위해 유형이 필요하지 않다는 것입니다. 메소드가 정의 된 경우이를 호출 할 수 있습니다.

그 이름은 "오리처럼 보이고 오리처럼, 거리면 오리입니다"라는 문구에서 유래합니다.

Wikipedia 에 훨씬 더 많은 정보가 있습니다.


25
강력한 타이핑 사용에주의하십시오. 잘 정의되지 않았습니다. 오리 타이핑도 아닙니다. Google Go 또는 Ocaml은 구조적 서브 타이핑 구성을 사용하는 정적으로 유형이 지정된 언어입니다. 이 오리 형 언어입니까?
나는 크랩 답변을 제공합니다

7
오리 타이핑에 대한 더 좋은 표현은 : "만약 오리라면 .. 그것은 저에게 충분합니다." 참조 pyvideo.org/video/1669/keynote-3 28:30 또는 youtube.com/watch?v=NfngrdLv9ZQ#t=1716
tovmeod

7
오리 타이핑은 반드시 동적 언어에서만 사용되는 것은 아닙니다. Objective-C는 동적 언어가 아니며 오리 타이핑을 사용합니다.
eyuelt

12
Python과 Ruby는 모두 강력한 유형의 언어이며 Duck Typing이 있습니다. 문자열 입력은 오리 입력이 없다는 것을 의미하지 않습니다.
alanjds

8
나는 이것을 downvoting하고있다. 오리 덕킹은 유형의 강도와 아무런 관련이 없으며 인터페이스를 구현하든간에 메소드가있는 객체를 사용할 수있는 능력입니다.
전자 Satis

209

덕 타이핑 은 오퍼레이션이 피연산자가 충족해야하는 요구 사항을 공식적으로 지정 하지 않고 제공된 것만으로 시도한다는 것을 의미 합니다 .

다른 사람들의 말과 달리, 이것은 반드시 동적 언어 나 상속 문제와 관련이있는 것은 아닙니다.

예제 작업 :Quack 객체에서 일부 메소드 를 호출하십시오 .

덕 타이핑을 사용 하지 않고이 f작업을 수행 하는 함수 는 해당 인수가 일부 메서드를 지원해야한다고 미리 지정해야 Quack합니다. 일반적인 방법은 인터페이스를 사용하는 것입니다

interface IQuack { 
    void Quack();
}

void f(IQuack x) { 
    x.Quack(); 
}

호출은 f(42)실패하지만 f(donald)만큼으로 작동 donald의 인스턴스 IQuack-subtype.

또 다른 접근 방식은 구조적 타이핑입니다 . 그러나이 방법 Quack()은 미리 공식적으로 지정 quack되어 있으므로 사전에 컴파일러 오류가 발생할 수 있습니다.

def f(x : { def Quack() : Unit }) = x.Quack() 

우리는 심지어 쓸 수 있었다

f :: Quackable a => a -> IO ()
f = quack

Haskell에서 Quackabletypeclass는 메소드의 존재를 보장합니다.


오리의 타이핑 은 어떻게 바뀌나요?

내가 말했듯이, 오리 타이핑 시스템은 요구 사항을 지정하지 않고 작동하는 경우에만 시도합니다 .

따라서 파이썬의 다이내믹 타입 시스템은 항상 오리 타이핑을 사용합니다.

def f(x):
    x.Quack()

경우 f가져 x을 지원하고 Quack(), 런타임시 충돌합니다하지 않을 경우, 모든 것이 괜찮습니다.

그러나 오리 타이핑은 동적 타이핑을 의미하지는 않습니다. 실제로 요구 사항을 제공하지 않는 매우 인기가 있지만 완전히 정적 인 오리 타이핑 방식이 있습니다.

template <typename T>
void f(T x) { x.Quack(); } 

이 기능은 일부 원하는 것을 어떤 방식으로 말하지 않는 x그 캔을 Quack너무 대신 그냥 시도, 컴파일시에 그것의 미세하고 모든 작업합니다.


5
당신은 의미하지 않았다 : void f (IQuak x) {x.Quak (); } 함수 f의 매개 변수가 IQuack x가 아닌 IQuack x이기 때문에 (K.Quack 대신) 아주 작은 실수이지만 수정이 필요하다고 느꼈습니다. :)
dominicbri7

Wikipedia에 따르면, 마지막 예제는 "Duck 타이핑"이 아니라 "구조적 타이핑"입니다.
Brilliand

글쎄, 그것은 그 토론에 대한 별도의 질문이있는 것 같습니다 : stackoverflow.com/questions/1948069/…
Brilliand

1
따라서 내가 말한 것을 이해하면 오리 타이핑을 지원하는 언어와 오리 타이핑이 아닌 언어의 차이점은 함수가 허용하는 객체 유형을 지정할 필요가 없습니까? def f(x)대신에 def f(IQuack x).
PProteus

124

간단한 설명 (코드없이)

질문의 의미론에 대한 토론은 상당히 미묘한 (그리고 매우 학문적이지만) 일반적인 아이디어는 다음과 같습니다.

오리 타이핑

(“오리처럼 걷고 오리처럼 If 거리면 오리입니다.”)- 그렇습니다! 그러나 그것은 무엇을 의미 하는가 ??! 이것은 예를 통해 가장 잘 설명됩니다.

오리 입력 기능의 예 :

마술 지팡이가 있다고 상상해보십시오. 특별한 힘이 있습니다. 지팡이를 흔들고 "드라이브!" 라고 말하면 그럼 차에 타요!

다른 것들에서도 작동합니까? 확실하지 않습니다 : 그래서 나는 트럭에서 그것을 시도하십시오. 와우-그것도 운전! 그런 다음 비행기, 기차 및 1 우즈에서 시도해보십시오 (사람들이 골프 공을 운전하는 데 사용하는 골프 클럽 유형입니다). 그들은 모두 운전한다!

그러나 그것은 찻잔이라고 할 수 있습니까? 오류 : KAAAA-BOOOOOOM! 그것은 잘 작동하지 않았다. ====> 찻잔은 운전할 수 없습니다 !! 어이!?

이것이 기본적으로 오리 타이핑의 개념입니다. 그것은 A의 시도 - 전에 - 당신 - 구매 시스템. 작동하면 모든 것이 잘됩니다. 그러나 수류탄이 손에 든 것처럼 실패하면 얼굴이 터질 것입니다.

다시 말해, 우리는 객체 아닌 객체가 무엇을 할 수 있는지에 관심 있습니다.

예 : 정적으로 입력 된 언어

객체가 실제로 무엇인지 에 대해 염려한다면 , 마술은 미리 설정된 승인 된 유형 (이 경우 자동차)에서만 작동하지만 트럭, 오토바이, 툭툭 등 운전할 수있는 다른 객체에서는 작동하지 않습니다 . 마술 지팡이가 자동차에서만 작동 하기를 기대하기 때문에 트럭에서는 작동하지 않습니다 .

다시 말해,이 시나리오에서 마술 지팡이는 물체 할 수있는 것 (예 : 자동차, 트럭 등을 운전할 수 있는지 )이 아니라 물체 무엇인지 (차입니까?)를 매우 면밀히 살펴 봅니다 .

트럭을 운전할 수있는 유일한 방법은 어쨌든 마술 지팡이가 트럭 자동차를 모두 예상 할 수있는 경우 (아마 "공통 인터페이스 구현")입니다. 그 의미를 모르는 경우 잠시 무시하십시오.

요약 : 주요 테이크 아웃

오리 타이핑에서 중요한 것은 객체 아닌 객체가 실제로 수 있는 것 입니다 .


나는 당신이 행동에 대해 더 관심을 갖는 것에 대한 전제를 흥미롭게 생각합니다. 그것이 바로 정의입니다. 의심 할 여지없이 BDD는 루비와 같은 언어에서 성공적입니다.
Pablo Olmos de Aguilera C.

27

간단한 함수를 디자인한다고 가정 해보십시오.이 함수는 유형의 객체를 가져 와서 메소드를 Bird호출합니다 walk(). 생각할 수있는 두 가지 접근 방식이 있습니다.

  1. 이것은 내 기능이며을 수락 Bird하거나 코드가 컴파일되지 않아야합니다. 누군가 내 기능을 사용하려면 Birds 만 수락한다는 것을 알고 있어야합니다.
  2. 내 함수는 아무것도 얻지 못하고 objects객체의 walk()메소드를 호출합니다 . 따라서 objectwalk()이 올바른 경우 내 기능을 사용할 수 없으면 실패합니다. 따라서 여기에서 객체가 중요하지는 않습니다 Bird. 이것이 중요합니다 walk() (이것은 오리 타이핑입니다 )

것을 고려되어야 오리 입력은 예를 들어 파이썬 용도, 어떤 경우에 유용 할 수 입력 오리 를 많이.


유용한 독서


1
좋은 설명, 어떤 장점이 있습니까?
sushil bharwani

2
이 답변은 간단하고 명확하며 초보자에게 가장 적합합니다. 위의 답과 함께이 답변 읽기 (또는이 이동하면, 대답이 차와 찻잔에 대해 이야기)
DORRITO

18

Wikipedia에 상당히 자세한 설명이 있습니다.

http://en.wikipedia.org/wiki/Duck_typing

덕 타이핑은 객체의 현재 메서드 및 속성 집합이 특정 클래스 또는 특정 인터페이스 구현에서 상속되지 않고 유효한 의미를 결정하는 동적 타이핑 스타일입니다.

중요한 점은 오리 타이핑을 사용하면 개발자가 실제 기본 유형이 아닌 소비되는 객체 부분에 더 관심이 있다는 것입니다.


13

오래된 관용구를 반복하는 많은 답변이 있습니다.

오리처럼 보이고 오리처럼 cks하면 오리

오리 타이핑으로 무엇을 할 수 있는지에 대한 설명이나 개념을 더 혼란스럽게 만드는 예를 들어보십시오.

그다지 도움이되지 않습니다.

이것은 내가 찾은 오리 타이핑에 대한 일반 영어 답변의 가장 좋은 시도입니다.

덕 타이핑 (Duck Typing)은 개체가 무엇을하는 것이 아니라 가능한 것으로 정의하는 것을 의미합니다.

즉, 객체의 클래스 / 유형에 대한 관심이 적고 어떤 메소드를 호출 할 수 있는지, 어떤 조작을 수행 할 수 있는지에 더 관심이 있습니다. 우리는 유형에 신경 쓰지 않고 할 수있는 일에 관심을 갖습니다 .


3

오리 타이핑 :

오리처럼 말하고 걷는다면 오리입니다

이것은 일반적이라고 납치 ( abductive 추론 또는라고도 retroduction , 내 생각을 명확하게 정의) :

  • 에서 C (결론, 우리가 무엇을보고 ) 및 R (규칙, 우리가 알고있는 ), 우리는 결정 / 동의 / 가정 P (전제, 재산 즉 주어진 사실을)

    ... 의료 진단의 기초

    오리 : C = 걷기, 대화 , R = 오리처럼 , P = 오리입니다

프로그래밍으로 돌아 가기 :

  • 객체 o 는 메쏘드 / 프로퍼티 mp1을 가지며 인터페이스 / 타입 Tmp1을 요구 / 정의한다

  • 객체 o 는 메소드 / 프로퍼티 mp2를 가지며 인터페이스 / 타입 Tmp2를 요구 / 정의한다

  • ...

그래서, 더 간단하게 받아들이는 것보다 MP1을 오래가 몇 가지 정의를 충족하는 것처럼 모든 개체에 ... MP1을 단언와 ..., 컴파일러 / 런타임도 괜찮을 것 같네요 오는 타입입니다 T

그리고 위의 예와 같은 경우입니까? 오리 타이핑은 본질적으로 타이핑이 아닙니까? 아니면 암시 적 타이핑이라고해야합니까?


3

언어 자체를 보면 도움이 될 수 있습니다. 그것은 종종 나를 도와줍니다 (나는 영어 원어민이 아닙니다).

에서 duck typing:

1) 단어 typing는 키보드로 타이핑하는 것을 의미하지 않으며 (내 마음 속의 영속적 인 이미지처럼) " 그것이 어떤 종류의 것입니까? "

2) 단어 duck는 그 결정이 어떻게 이루어 졌는지를 나타낸다. 다음과 같이 '느슨한'결정입니다. " 오리처럼 걷는다면 오리 입니다." 물건이 오리 일 수도 있고 아닐 수도 있기 때문에 '느슨한'것이지만 실제로 오리인지는 중요하지 않습니다. 중요한 것은 오리와 함께 할 수 있고 오리의 행동을 기대한다는 것입니다. 나는 빵 부스러기를 먹일 수 있고 물건은 나에게 가거나 나에게 청구하거나 물러날 수 있습니다 ...하지만 그리즐리처럼 나를 삼키지 않을 것입니다.


2

나는 일반적인 답변을 제공하지 않는다는 것을 알고 있습니다. 루비에서는 변수 나 메소드의 유형을 선언하지 않습니다. 모든 것이 일종의 객체 일뿐입니다. 규칙은 "유형이 아닌 클래스"입니다

루비에서 클래스는 결코 타입이 아닙니다. 대신, 객체의 유형은 해당 객체가 수행 할 수있는 작업에 의해 더 정의됩니다. 루비에서는 이것을 오리 입력이라고합니다. 물체가 오리처럼 걷거나 오리처럼 말하면 통역사는 그것을 오리처럼 취급합니다.

예를 들어, 노래 정보를 문자열에 추가하는 루틴을 작성 중일 수 있습니다. C # 또는 Java 배경에서 온 경우 다음을 작성하려고 할 수 있습니다.

def append_song(result, song)
    # test we're given the right parameters 
    unless result.kind_of?(String)
        fail TypeError.new("String expected") end
    unless song.kind_of?(Song)
        fail TypeError.new("Song expected")
end

result << song.title << " (" << song.artist << ")" end
result = ""

append_song(result, song) # => "I Got Rhythm (Gene Kelly)"

Ruby의 오리 타이핑을 받아들이면 훨씬 간단한 것을 작성할 수 있습니다.

def append_song(result, song)
    result << song.title << " (" << song.artist << ")"
end

result = ""
append_song(result, song) # => "I Got Rhythm (Gene Kelly)"

인수 유형을 확인할 필요가 없습니다. 그들이 << (결과의 경우) 또는 제목과 아티스트 (노래의 경우)를 지원하면 모든 것이 작동합니다. 그렇지 않으면 어쨌든 메소드는 예외를 throw합니다 (유형을 확인했을 때와 마찬가지로). 그러나 확인하지 않으면 방법이 갑자기 훨씬 유연합니다. 배열, 문자열, 파일 또는 <<를 사용하여 추가하는 다른 객체를 전달하면 작동합니다.


2

오리 타이핑은 유형 힌트가 아닙니다!

기본적으로 "오리 타이핑"을 사용하기 위해 공통 인터페이스를 사용하여 특정 유형을 대상으로하지 않고보다 광범위한 하위 유형 (상속에 대해 이야기하지 않고 하위 유형을 의미 할 때 동일한 프로파일 내에 맞는 "사물"을 의미 함)을 대상으로합니다. .

정보를 저장하는 시스템을 상상할 수 있습니다. 정보를 쓰거나 읽으려면 일종의 스토리지와 정보가 필요합니다.

스토리지 유형은 파일, 데이터베이스, 세션 등일 수 있습니다.

인터페이스는 스토리지 유형에 관계없이 사용 가능한 옵션 (방법)을 알려줍니다. 이는 현재 구현 된 것이 없음을 의미합니다! 다시 말해서 인터페이스는 정보를 저장하는 방법에 대해 아무것도 모른다.

모든 스토리지 시스템은 인터페이스가 동일한 방법을 구현하여 인터페이스의 존재를 알아야합니다.

interface StorageInterface
{
   public function write(string $key, array $value): bool;
   public function read(string $key): array;
}


class File implements StorageInterface
{
    public function read(string $key): array {
        //reading from a file
    }

    public function write(string $key, array $value): bool {
         //writing in a file implementation
    }
}


class Session implements StorageInterface
{
    public function read(string $key): array {
        //reading from a session
    }

    public function write(string $key, array $value): bool {
         //writing in a session implementation
    }
}


class Storage implements StorageInterface
{
    private $_storage = null;

    function __construct(StorageInterface $storage) {
        $this->_storage = $storage;
    }

    public function read(string $key): array {
        return $this->_storage->read($key);
    }

    public function write(string $key, array $value): bool {
        return ($this->_storage->write($key, $value)) ? true : false;
    }
}

따라서 이제 정보를 쓰거나 읽을 때마다 :

$file = new Storage(new File());
$file->write('filename', ['information'] );
echo $file->read('filename');

$session = new Storage(new Session());
$session->write('filename', ['information'] );
echo $session->read('filename');

이 예제에서는 저장소 생성자에서 Duck Typing을 사용합니다.

function __construct(StorageInterface $storage) ...

그것이 도움이되기를 바랍니다.)


2

오리 입력 기술을 사용한 트리 탐색

def traverse(t):
    try:
        t.label()
    except AttributeError:
        print(t, end=" ")
    else:
        # Now we know that t.node is defined
        print('(', t.label(), end=" ")
        for child in t:
            traverse(child)
        print(')', end=" ")

0

동적 타이핑, 정적 타이핑 및 오리 타이핑을 혼합하는 것이 혼란 스럽다고 생각합니다. 오리 타이핑은 독립적 인 개념이며 Go와 같은 정적 타입의 언어는 오리 타이핑을 구현하는 타입 검사 시스템을 가질 수 있습니다. 타입 시스템이 (선언 된) 객체의 메소드를 검사하지만 타입은 검사하지 않는 경우이를 오리 타이핑 언어라고 할 수 있습니다.


-1

나는 유명한 문장을 내 방식으로 이해하려고 노력한다. "파이썬은 개체를 돌보지 않는 것이 실제 오리인지 아닌지이다. 개체는 첫 번째 '척', 두 번째는 '오리처럼'이다."

좋은 웹 사이트가 있습니다. http://www.voidspace.org.uk/python/articles/duck_typing.shtml#id14

필자는 오리 타이핑을 사용하면 자체 내부 데이터 구조를 가진 고유 한 클래스를 만들 수 있지만 일반적인 Python 구문을 사용하여 액세스 할 수 있다고 지적했습니다.

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