동적 타이핑은 어떤 기능을 허용합니까? [닫은]


91

나는 며칠 동안 파이썬을 사용 해 왔으며 동적 입력과 정적 입력의 차이점을 이해한다고 생각합니다. 내가 이해하지 못하는 것은 어떤 상황에서 선호되는지입니다. 융통성 있고 읽기 쉬우나 더 많은 런타임 검사 및 추가 필요한 단위 테스트를 희생합니다.

유연성 및 가독성과 같은 비 기능적 기준 외에도 동적 타이핑을 선택해야하는 이유는 무엇입니까? 그렇지 않으면 불가능한 동적 입력으로 무엇을 할 수 있습니까? 동적 타이핑의 구체적인 장점을 보여주는 특정 코드 예제는 무엇입니까?


5
이론적으로 언어가 Turing Complete 인 한 , 당신이 할 수있는 일은 없습니다 . 나에게 더 흥미로운 질문은 한 대 다른 것보다 쉽고 자연스러운 것입니다. 파이썬에서 정기적으로하는 일이 가능하지만 C ++에서는 고려하지 않을 것들이 있습니다.
Mark Ransom

28
Chris Smith는 자신의 훌륭한 에세이에서 타이핑 시스템에 대해 토론하기 전에 알아야 할 내용을 다음과 같이 말합니다. "이 경우 문제는 대부분의 프로그래머가 경험이 제한적이며 많은 언어를 시도하지 않았다는 것입니다. "많은"것으로 계산되지 않습니다. ... 이것의 두 가지 흥미로운 결과는 다음과 같습니다. (1) 많은 프로그래머가 정적으로 유형이 낮은 언어를 사용했습니다. (2) 많은 프로그래머가 동적으로 유형이 지정된 언어를 매우 잘못 사용했습니다. "
Daniel Pryden

3
@suslik : 언어 프리미티브에 무의미한 유형이있는 경우 물론 유형에 무의미한 작업을 수행 할 수 있습니다. 정적 및 동적 입력의 차이점과는 아무런 관련이 없습니다.
Jon Purdy

10
@CzarekTomczak : 그것은 동적 타입 언어의 특징입니다. 그러나 정적 형식 언어는 런타임에 수정 될 수 있습니다. 예를 들어 Visual Studio를 사용하면 디버거에서 중단 점에있는 동안 C # 코드를 다시 작성하고 명령 포인터를 되 감아 코드를 새로운 변경 사항으로 다시 실행할 수도 있습니다. 다른 의견에서 Chris Smith를 인용 한 것처럼 "많은 프로그래머들이 정적으로 유형이 매우 낮은 언어를 사용했습니다"라고 알고 있습니다. 정적으로 유형이 지정된 언어를 모두 판단하지는 마십시오.
Daniel Pryden

11
@WarrenP : "동적 타입 시스템은 입력해야 할 추가 크루프의 양을 줄인다"고 주장하지만 파이썬과 C ++를 비교합니다. 물론 C ++은 파이썬보다 더 장황하지만 유형 시스템의 차이 때문이 아니라 문법의 차이 때문입니다. 프로그램 소스의 문자 수를 줄이려면 J 또는 APL을 배우십시오. 문자가 짧아 질 것입니다. 좀 더 공정한 비교는 파이썬과 하스켈을 비교하는 것입니다. (레코드 : 저는 파이썬을 좋아하고 C ++보다 선호하지만 하스켈을 더 좋아합니다.)
Daniel Pryden

답변:


50

구체적인 예를 요청 했으므로 알려 드리겠습니다.

Rob Conery의 대규모 ORM은 400 줄의 코드입니다. Rob은 SQL 테이블을 미러링하기 위해 많은 정적 유형을 요구하지 않고 SQL 테이블을 맵핑하고 오브젝트 결과를 제공 할 수 있기 때문에 작습니다. 이것은 dynamicC # 의 데이터 형식 을 사용하여 수행됩니다 . Rob의 웹 페이지에서이 프로세스에 대해 자세히 설명하지만이 특정 사용 사례에서는 동적 타이핑이 코드의 간결성을 담당하는 것으로 보입니다.

정적 유형을 사용하는 Sam Saffron의 Dapper 와 비교하십시오 . SQLMapper클래스는 혼자 코드 3000 개 라인입니다.

일반적인 면책 조항이 적용되며 마일리지는 다를 수 있습니다. Dapper는 Massive와는 다른 목표를 가지고 있습니다. 동적 타이핑 없이는 불가능한 400 줄의 코드로 할 수있는 일의 예로 이것을 지적했습니다.


동적 타이핑을 사용하면 유형 결정을 런타임 으로 연기 할 수 있습니다 . 그게 다야.

동적 형식 언어를 사용하든 정적 형식 언어를 사용하든 유형 선택은 여전히 ​​합리적이어야합니다. 문자열에 숫자 데이터가 포함되어 있지 않으면 두 개의 문자열을 함께 추가하지 않고 숫자 답변을 기대할 수 있으며 그렇지 않은 경우 예기치 않은 결과가 발생합니다. 정적으로 입력 된 언어를 사용하면 처음에는 그렇게 할 수 없습니다.

정적 타입 언어의 지지자들은 컴파일러가 한 줄이 실행되기 전에 컴파일 타임에 코드를 상당량 "위생성 검사"할 수 있다고 지적합니다. 이것은 Good Thing ™입니다.

C #에는 dynamic키워드가 있으므로 나머지 코드에서 정적 유형 안전의 이점을 잃지 않으면 서 유형 결정을 런타임으로 연기 할 수 있습니다. 타입 추론 ( var)은 타입을 항상 명시 적으로 선언 할 필요가 없어서 정적으로 타입이 지정된 언어로 작성하는 고통을 상당 부분 제거합니다.


동적 언어는 프로그래밍에 대한 대화식의 즉각적인 접근 방식을 선호합니다. 아무도 클래스를 작성하고 컴파일주기를 거쳐 Lisp 코드를 입력하고 실행하는 것을 기대하지 않습니다. 그러나 이것이 정확히 C #에서 기대하는 것입니다.


22
두 개의 숫자 문자열을 함께 추가해도 숫자 결과는 기대하지 않습니다.
pdr

22
@Robert 나는 대부분의 답변에 동의합니다. 그러나 Scala 및 Haskell과 같은 대화식 읽기 평가 인쇄 루프가있는 정적으로 유형이 지정된 언어가 있습니다. C #은 특히 대화 형 언어가 아닐 수도 있습니다.
Andres F.

14
하스켈을 배워야 해
Robert Harvey

7
@RobertHarvey : 아직 시도하지 않았다면 F #에 놀랐을 것입니다. 거의 모든 유형을 선언 할 필요가 없다는 점을 제외하고 일반적으로 .NET 언어로 제공되는 모든 (컴파일 타임) 유형 안전성을 얻습니다. F #의 형식 유추는 C #에서 사용할 수있는 것 이상의 것입니다. 또한 : F # 대화 형 비주얼 스튜디오의 일부 ... 안드레스 다니엘이 지적하는 것과 비슷합니다
스티븐 에버스

8
"문자열에 숫자 데이터가 포함되어 있지 않으면 두 개의 문자열을 함께 추가하지 않고 숫자 답변을 기대할 수 있으며 그렇지 않은 경우 예기치 않은 결과가 발생합니다" 죄송합니다. 동적 및 정적 입력 과는 아무 관련이 없습니다. , 이것은 강하고 약한 타이핑입니다.
vartec

26

"정적 타이핑"및 "동적 타이핑"과 같은 문구가 많이 사용되며 사람들은 미묘하게 다른 정의를 사용하는 경향이 있으므로 의미를 명확히하여 시작하겠습니다.

컴파일 타임에 검사되는 정적 유형을 가진 언어를 고려하십시오. 그러나 유형 오류는 치명적이지 않은 경고 만 생성하며 런타임에 모든 유형은 오리 유형입니다. 이 정적 유형은 프로그래머의 편의를 위해서만 제공되며 codegen에는 영향을 미치지 않습니다. 이는 정적 타이핑 자체가 제한을 두지 않으며 동적 타이핑과 상호 배타적이지 않음을 보여줍니다. (Objective-C는 이와 비슷합니다.)

그러나 대부분의 정적 유형 시스템은이 방식으로 작동하지 않습니다. 정적 유형 시스템에는 다음과 같은 두 가지 공통 속성이 있습니다.

컴파일러는 정적 유형 오류가 포함 된 프로그램을 거부 할 수 있습니다.

많은 유형 안전 프로그램에 반드시 정적 유형 오류가 포함되기 때문에 이는 제한 사항입니다.

예를 들어 Python 2와 Python 3으로 실행 해야하는 Python 스크립트가 있습니다. 일부 함수는 Python 2와 3 사이에서 매개 변수 유형을 변경 했으므로 다음과 같은 코드가 있습니다.

if sys.version_info[0] == 2:
    wfile.write(txt)
else:
    wfile.write(bytes(txt, 'utf-8'))

Python 2 정적 유형 검사기는 실행되지 않더라도 Python 3 코드를 거부합니다 (또는 그 반대). 내 유형 안전 프로그램에 정적 유형 오류가 있습니다.

다른 예로, OS X 10.6에서 실행 되길 원하지만 10.7의 새로운 기능을 활용하는 Mac 프로그램을 고려하십시오. 10.7 메소드는 런타임에 존재할 수도 있고 존재하지 않을 수도 있으며, 프로그래머는 나를 감지합니다. 정적 형식 검사기는 형식 안전을 보장하기 위해 내 프로그램을 거부하거나 런타임에 형식 오류 (함수 없음)가 발생할 가능성과 함께 프로그램을 수락해야합니다.

정적 유형 검사는 런타임 환경이 컴파일 시간 정보에 의해 적절하게 설명되어 있다고 가정합니다. 그러나 미래를 예측하는 것은 위험합니다!

한 가지 더 제한 사항이 있습니다.

컴파일러는 런타임 유형이 정적 유형이라고 가정하는 코드를 생성 할 수 있습니다.

정적 유형이 "정확"하다고 가정하면 최적화에 대한 많은 기회가 제공되지만 이러한 최적화는 제한적일 수 있습니다. 좋은 예는 원격과 같은 프록시 객체입니다. 다른 프로세스에서 메소드 호출을 실제 오브젝트로 전달하는 로컬 프록시 오브젝트를 원한다고 가정하십시오. 프록시가 일반 (따라서 객체로 가장 할 수 있음) 투명하고 (기존 코드가 프록시와 통신하고 있음을 알 필요가 없도록) 투명하면 좋을 것입니다. 그러나이를 위해 컴파일러는 정적 유형을 올바른 것으로 가정하는 코드를 생성 할 수 없습니다 (예 : 정적 인라인 메소드 호출). 객체가 실제로 프록시 인 경우 실패하기 때문에 실패합니다.

이러한 원격 기능의 예로는 ObjC의 NSXPCConnection 또는 C #의 TransparentProxy가 있습니다 (이 구현에는 런타임에 약간의 비관 화가 필요했습니다- 여기 를 참조 하십시오 ).

codegen이 정적 유형에 의존하지 않고 메시지 전달과 같은 기능이있는 경우 프록시 객체, 디버깅 등으로 많은 멋진 작업을 수행 할 수 있습니다.

타입 체커를 만족시킬 필요가없는 경우에 할 수있는 것들 중 일부를 샘플링 한 것입니다. 정적 유형이 아니라 강제 정적 유형 검사에 의해 제한이 적용됩니다.


2
"Python 2 정적 유형 검사기는 실행되지 않더라도 Python 3 코드를 거부합니다 (그 반대도 마찬가지 임). 유형 안전 프로그램에 정적 유형 오류가 포함되어 있습니다." 당신이 정말로 필요로하는 것 같은 어떤 종류의 "정적 if"가 있는데, 여기서 컴파일러 / 인터프리터는 조건이 거짓 인 경우에도 코드를 볼 수 없습니다.
David Stone

C ++에 존재하는 @davidstone
Milind R

A Python 2 static type checker would reject the Python 3 code (and vice versa), even though it would never be executed. My type safe program contains a static type error. 합리적인 정적 언어에서는 IFDEF두 가지 경우 모두 형식 안전을 유지하면서 형식 프리 프로세서 문을 사용 하여이 작업을 수행 할 수 있습니다 .
메이슨 휠러

1
@MasonWheeler, davidstone 아니요, 전 처리기 트릭 및 static_if가 모두 정적입니다. 필자의 예제에서는 Python2와 Python3을 사용했지만 AmazingModule2.0 및 AmazingModule3.0과 같이 쉽게 인터페이스를 사용할 수 있었으며 일부 인터페이스는 버전간에 변경되었습니다. 인터페이스를 가장 빨리 알 수있는 것은 모듈 가져 오기 시간이며, 반드시 런타임에 있어야합니다 (적어도 동적 연결을 지원하려는 경우).
ridiculous_fish

18

오리 유형 변수는 모든 사람이 가장 먼저 생각하는 것이지만 대부분의 경우 정적 유형 유추를 통해 동일한 이점을 얻을 수 있습니다.

그러나 동적으로 생성 된 컬렉션에서 오리 입력은 다른 방법으로는 달성하기 어렵습니다.

>>> d = JSON.parse(foo)
>>> d['bar'][3]
12
>>> d['baz']['qux']
'quux'

그렇다면 어떤 유형이 JSON.parse반환됩니까? 정수 배열 또는 사전 문자열 배열의 사전? 아니, 그것조차 충분하지 않습니다.

JSON.parsenull, bool, float, string, 이러한 유형의 배열을 재귀 적으로 배열하거나 문자열에서 이러한 유형을 재귀 적으로 사전으로 분류 할 수있는 일종의 "variant value"를 반환해야합니다. 동적 타이핑의 주요 장점은 이러한 변형 유형을 갖는 것입니다.

지금까지는 동적 유형 언어가 아니라 동적 유형 의 이점이 있습니다. 적절한 정적 언어는 이러한 유형을 완벽하게 시뮬레이션 할 수 있습니다. (그리고 "나쁜"언어조차도 종종 유형 안전을 깨뜨 리거나 서투른 액세스 구문을 요구하여 언어를 시뮬레이션 할 수 있습니다.)

동적 형식 언어의 장점은 정적 형식 유추 시스템에서 이러한 형식을 유추 할 수 없다는 것입니다. 유형을 명시 적으로 작성해야합니다. 그러나 한 번만 포함하여 이러한 유형을 설명하는 코드는 유형을 설명하지 않고 객체를 구문 분석 / 구성하는 코드와 마찬가지로 복잡하므로 반드시 이점은 아닙니다.


21
대수 데이터 형식으로 JSON 구문 분석 예제를 정적으로 쉽게 처리 할 수 있습니다 .

2
내 대답은 명확하지 않았다. 감사. JSValue는 동적 유형의 명시 적 정의이며 정확히 내가 말한 것입니다. 동적 타이핑이 필요한 언어가 아닌 유용한 동적 유형입니다. 그러나 동적 유형은 실제 유형 유추 시스템에서 자동으로 생성 할 수 없지만 사람들이 일반적으로 추론 할 수있는 대부분의 일반적인 예는 여전히 적합하지 않습니다. 새 버전이 더 잘 설명되기를 바랍니다.
abarnert

4
@MattFenwick 대수 데이터 타입은 (실제로) 기능적 언어로 제한됩니다. Java 및 C #과 같은 언어는 어떻습니까?
spirc

4
ADT는 C / C ++에서 태그 결합으로 존재합니다. 이것은 기능적 언어에 고유하지 않습니다.
Clark Gaebel

2
@spirc @ 공통 인터페이스, getClass () 또는 GetType ()에 대한 런타임 호출 및 동등성 검사에서 파생 된 여러 클래스를 사용하여 클래식 OO 언어로 ADT를 에뮬레이션 할 수 있습니다. 또는 이중 디스패치를 ​​사용할 수는 있지만 C ++에서 더 많이 지불한다고 생각합니다. 따라서 JSObject 인터페이스와 JSString, JSNumber, JSHash 및 JSArray 클래스가있을 수 있습니다. 그런 다음이 "형식화되지 않은"데이터 구조를 "응용 프로그램 형식의"데이터 구조로 바꾸려면 약간의 코드가 필요합니다. 그러나 동적 유형 언어로도이 작업을 수행하려고합니다.
Daniel Yankowsky

12

모든 원격 실용 정적 유형 시스템은 관련된 프로그래밍 언어에 비해 심각하게 제한되므로 런타임에 코드가 확인할 수있는 모든 불변을 표현할 수는 없습니다. 유형 시스템이 제공하려는 보증을 회피하지 않기 위해, 이러한 점검을 통과하지만 유형 시스템에서 입증 될 수없는 사용 사례는 보수적이고 허용하지 않는 것을 선택합니다.

예를 들어 보겠습니다. 모델이 xFoo 유형의 객체 속성 이 정수를 가지고 있다고 말하면 항상 정수를 가져야 한다는 의미에서 정적으로 유형이 지정된 데이터 객체, 데이터 수집 등을 설명하기 위해 간단한 데이터 모델을 구현한다고 가정하십시오 . 이것은 런타임 구성이므로 정적으로 입력 할 수 없습니다. YAML 파일에 설명 된 데이터를 저장한다고 가정하십시오. 해시 맵을 생성하고 (나중에 YAML 라이브러리로 전달) x속성을 가져와 맵에 저장 한 다음 문자열과 같은 다른 속성을 가져옵니다. 지금의 유형은 무엇입니까 the_map[some_key]? 그럼 우리가 알다시피, 촬영 some_key이며 'x'그 결과는 따라서 정수 여야하지만, 타입 시스템도 이것에 대해 추론을 시작할 수 없습니다.

적극적으로 연구 된 형식 시스템은이 특정 예제에서 작동 할 수 있지만, 특히 컴파일러 작성자가 구현하고 프로그래머가 추론하기에는 너무 복잡합니다. 특히이 "단순한"항목에 ​​대해서는 매우 복잡합니다. 절).

물론 오늘날의 솔루션은 모든 것을 박스에 넣은 다음 캐스팅 (또는 구현되지 않은 예외를 발생시키는 많은 오버라이드 된 메소드를 갖는 것)입니다. 그러나 이것은 정적으로 유형이 아니라 런타임에 유형 검사를 수행하는 유형 시스템 주위의 해킹 입니다.


제네릭 형식에는 권투 요구 사항이 없습니다.
Robert Harvey

@RobertHarvey 예. 내가 얘기하지 않은 자바 C #에서 복싱, 나는 "그 목적 U의 하위 유형에서 T의 값을 나타내는 일부 래퍼 클래스를 마무리"에 대해 얘기했다. 그러나 매개 변수 다형성 (일반적인 타이핑이라고 부르는 것)은 내 예제에는 적용되지 않습니다. 구체적인 유형에 대한 컴파일 타임 추상화이지만 런타임 입력 메커니즘이 필요합니다.

Scala의 타입 시스템이 Turing complete임을 지적하는 것이 좋습니다. 따라서 타입 시스템은 그림보다 덜 사소 할 수 있습니다.
Andrea

@Andrea 나는 의도적으로 튜링 완전성에 대한 설명을 줄이지 않았습니다. 타르타르 타르트에서 프로그래밍 한 적이 있습니까? 아니면 이러한 것들을 유형으로 인코딩하려고 했습니까? 어떤 시점에서는 실현하기에는 너무 복잡해집니다.

@delnan 동의합니다. 방금 유형 시스템이 상당히 복잡한 작업을 수행 할 수 있다고 지적했습니다. 나는 당신의 대답이 타입 시스템이 사소한 검증 만 할 수 있다는 것을 의미한다고 생각했지만, 두 번째 읽을 때 이와 같은 것을 쓰지 않았습니다!
Andrea

7

정적 입력 언어로는 동적 입력을 구현할 수 있기 때문에 정적 입력으로는 할 수없는 동적 입력으로 할 수있는 일은 없습니다.

하스켈의 짧은 예 :

data Data = DString String | DInt Int | DDouble Double

-- defining a '+' operator here, with explicit promotion behavior
DString a + DString b = DString (a ++ b)
DString a + DInt b = DString (a ++ show b)
DString a + DDouble b = DString (a ++ show b)
DInt a + DString b = DString (show a ++ b)
DInt a + DInt b = DInt (a + b)
DInt a + DDouble b = DDouble (fromIntegral a + b)
DDouble a + DString b = DString (show a ++ b)
DDouble a + DInt b = DDouble (a + fromIntegral b)
DDouble a + DDouble b = DDouble (a + b)

충분한 경우 충분한 동적 유형 시스템을 구현할 수 있습니다.

반대로, 정적으로 유형이 지정된 프로그램을 동등한 동적 프로그램으로 변환 할 수도 있습니다. 물론 정적으로 유형이 지정된 언어가 제공하는 정확성에 대한 모든 컴파일 타임 보장을 잃게됩니다.

편집 : 나는 이것을 간단하게 유지하고 싶었지만 여기에 객체 모델에 대한 자세한 내용이 있습니다.

함수는 Data 목록을 인수로 사용하고 ImplMonad에서 부작용이있는 계산을 수행하고 Data를 리턴합니다.

type Function = [Data] -> ImplMonad Data

DMember 멤버 값이거나 함수입니다.

data DMember = DMemValue Data | DMemFunction Function

Data객체와 함수를 포함하도록 확장하십시오 . 개체는 명명 된 멤버의 목록입니다.

data Data = .... | DObject [(String, DMember)] | DFunction Function

이 정적 형식은 내가 익숙한 모든 동적 형식의 개체 시스템을 구현하기에 충분합니다.


의 정의를 다시 방문하지 않고 새 유형을 추가 할 수 없기 때문에 전혀 다릅니다 Data.
Jed

5
예제에서 동적 타이핑 개념을 약한 타이핑과 혼합하고 있습니다. 동적 타이핑은 허용되는 유형의 목록을 정의하지 않고 알 수없는 유형에서 작동하는 것과 그 사이의 과부하 작업에 관한 것입니다.
hcalves

2
@Jed 객체 모델, 기본 유형 및 기본 작업을 구현 한 후에는 다른 기초가 필요하지 않습니다. 원래의 동적 언어로 된 프로그램을이 언어로 쉽고 자동으로 번역 할 수 있습니다.
NovaDenizen

2
@hcalves Haskell 코드에서 오버로드를 언급하고 있기 때문에 의미에 대한 올바른 아이디어가 없다고 생각합니다. +Data값을 다른 값으로 결합 하는 새 연산자를 정의했습니다 Data. Data동적 유형 시스템의 표준 값을 나타냅니다.
NovaDenizen

1
@Jed : 대부분의 동적 언어에는 작은 "기본"유형 세트와 새로운 값 (목록과 같은 데이터 구조)을 도입하는 귀납적 인 방법이 있습니다. 예를 들어, 계획은 원자, 쌍 및 벡터보다 훨씬 더 멀리 떨어져 있습니다. 주어진 동적 유형의 나머지와 동일한 방식으로이를 구현할 수 있어야합니다.
Tikhon Jelvis

3

:

멤브레인은 단일 객체의 래퍼가 아니라 전체 객체 그래프를 감싸는 래퍼입니다. 일반적으로 막의 제작자는 막에 하나의 물체 만 포장하기 시작합니다. 핵심 아이디어는 멤브레인을 가로 지르는 모든 객체 참조 자체가 동일한 멤브레인에 전 이적으로 감싸 져 있다는 것입니다.

여기에 이미지 설명을 입력하십시오

각 유형은 인터페이스는 동일하지만 메시지를 가로 채고 막을 가로 지르는 값을 줄 바꿈 및 줄 바꿈하는 유형으로 줄 바꿈됩니다. 좋아하는 정적으로 유형이 지정된 언어에서 랩 기능의 유형은 무엇입니까? 아마도 Haskell은 그 함수에 대한 유형을 가지고 있지만 대부분의 정적으로 유형이 지정된 언어는 Object → Object를 사용하지 않거나 결국 유형 검사기의 책임을 효과적으로 무효화합니다.


4
예, Haskell은 실존 유형을 사용하여 실제로이 작업을 수행 할 수 있습니다. Foo 유형 클래스가있는 경우 해당 인터페이스를 인스턴스화하는 모든 유형을 래퍼로 만들 수 있습니다. class Foo a where ... data Wrapper = forall a. Foo a => Wrapper a
Jake McArthur

@JakeMcArthur, 설명해 주셔서 감사합니다. 그것이 내가 하스켈을 배우고 배우는 또 다른 이유입니다.
Mike Samuel

2
멤브레인은 '인터페이스'이고 객체의 유형은 "실제적으로 유형이 지정되어 있습니다". 즉, 인터페이스 아래에 존재한다는 것을 알고 있지만 이것이 우리가 아는 전부입니다. 데이터 추상화를위한 기존 유형은 80 년대부터 알려져 있습니다. 좋은 참고 자료는 cs.cmu.edu/~rwh/plbook/book.pdf입니다. 21.1 장
Don Stewart

@DonStewart. 그렇다면 Java 프록시 클래스는 실존 유형 메커니즘입니까? 막이 어려워지는 곳 중 하나는 해당 유형의 정의 외부에서 콘크리트 유형의 이름을 볼 수있는 명목 유형 시스템이있는 언어입니다. 예를 들어, StringJava에서는 구체적 유형이므로 랩핑 할 수 없습니다 . Smalltalk는 입력을 시도하지 않기 때문에이 문제가 없습니다 #doesNotUnderstand.
Mike Samuel

1

누군가 언급했듯이 이론 상으로는 특정 메커니즘을 직접 구현할 경우 정적 타이핑으로 할 수없는 동적 타이핑으로 할 수있는 일은 거의 없습니다. 대부분의 언어는 void 포인터, 루트 객체 유형 또는 빈 인터페이스와 같은 유형 유연성을 지원하는 유형 완화 메커니즘을 제공합니다.

더 나은 질문은 특정 상황과 문제에서 동적 타이핑이 더 적합하고 더 적합한 이유입니다.

먼저 정의하자

엔티티 -코드에서 일부 엔티티에 대한 일반적인 개념이 필요합니다. 프리미티브 수부터 복잡한 데이터까지 다양합니다.

행동 -우리의 실체가 외부 세계가 그 실체를 특정 반응에 지시 할 수있게하는 어떤 상태와 일련의 방법을 가지고 있다고하자. 이 엔티티의 상태 + 인터페이스에 해당 동작을 호출 할 수 있습니다. 하나의 엔티티는 언어가 제공하는 도구에 의해 특정 방식으로 둘 이상의 동작을 결합 할 수 있습니다 .

엔터티 및 해당 동작 정의 -모든 언어는 프로그램에서 특정 엔터티의 동작 (메소드 집합 + 내부 상태)을 정의하는 데 도움이되는 몇 가지 추상화 수단을 제공합니다. 이러한 동작에 이름을 할당하고이 동작이있는 모든 인스턴스가 특정 유형이라고 말할 수 있습니다 .

이것은 아마도 익숙하지 않은 것입니다. 그리고 당신이 말했듯이 당신은 차이를 이해했지만 여전히. 아마도 완전하고 가장 정확한 설명은 아니지만 약간의 가치를 가져올 수 있기를 바랍니다. :)

정적 타이핑 -코드 실행을 시작하기 전에 프로그램의 모든 엔터티의 동작을 컴파일 타임에 검사합니다. 이것은 예를 들어 Person 유형의 엔티티가 마술사처럼 행동하기를 원한다면 엔티티 MagicianPerson을 정의하고 throwMagic ()과 같은 마술사의 행동을 제공해야 함을 의미합니다. 코드에있는 경우 실수로 일반 Person.throwMagic () 컴파일러에게 알려주십시오."Error >>> hell, this Person has no this behavior, dunno throwing magics, no run!".

동적 타이핑 -동적 타이핑 환경에서 특정 엔티티로 무언가를 시도 할 때까지 엔티티의 사용 가능한 동작을 확인하지 않습니다. Person.throwMagic ()을 요청하는 Ruby 코드를 실행하면 코드가 실제로 올 때까지 잡히지 않습니다. 실망스럽지 않습니까? 그러나 그것은 또한 진동처럼 들립니다. 이 숙박 시설을 기반으로 흥미로운 일을 할 수 있습니다. 예를 들어, 어떤 것이 마술사에게 도움이 될 수있는 게임을 설계하고 코드의 특정 지점에 도달 할 때까지 누가 그렇게 될지 모른다고 가정 해 봅시다. 그리고 개구리가 와서HeyYouConcreteInstanceOfFrog.include Magic그때부터이 개구리는 마법의 힘을 가진 하나의 특정 개구리가됩니다. 다른 개구리는 아직 없습니다. 정적 입력 언어에서는 인터페이스 구현과 같은 동작의 표준 조합으로이 관계를 정의해야합니다. 동적 타이핑 언어에서는 런타임에 그렇게 할 수 있으며 아무도 신경 쓰지 않습니다.

대부분의 동적 타이핑 언어에는 인터페이스로 전달되는 모든 메시지를 포착하는 일반적인 동작을 제공하는 메커니즘이 있습니다. 예를 들어 내가 기억한다면 루비 method_missing와 PHP __call. 즉, 프로그램 실행 시간에 모든 종류의 흥미로운 작업을 수행하고 현재 프로그램 상태에 따라 유형을 결정할 수 있습니다. 이를 통해 Java와 같은 보수적 인 정적 프로그래밍 언어보다 훨씬 유연한 문제를 모델링 할 수있는 도구가 제공됩니다.

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