Aleks Bromfield의 주장 은 다음과 같습니다.
정적 유형 시스템을 가진 거의 모든 언어에는 동적 유형 시스템이 있습니다. C를 제외하고는 예외를 생각할 수 없습니다.
이것이 유효한 주장입니까? 런타임에 리플렉션 또는 로딩 클래스를 사용하면 Java가 약간 비슷하다는 것을 이해하지만 '점진적 타이핑'이라는 아이디어를 많은 언어로 확장 할 수 있습니까?
Aleks Bromfield의 주장 은 다음과 같습니다.
정적 유형 시스템을 가진 거의 모든 언어에는 동적 유형 시스템이 있습니다. C를 제외하고는 예외를 생각할 수 없습니다.
이것이 유효한 주장입니까? 런타임에 리플렉션 또는 로딩 클래스를 사용하면 Java가 약간 비슷하다는 것을 이해하지만 '점진적 타이핑'이라는 아이디어를 많은 언어로 확장 할 수 있습니까?
답변:
원래 트위터 여기에. :)
우선, 나는 내 트윗이 너무 심각하게 받아 들여지는 것에 대해 다소 즐겁고 충격을 받았습니다! 이것이 널리 보급 될 것이라는 것을 알았다면, 그것을 작성하는 데 30 초 이상이 걸렸을 것입니다!
Thiago Silva는 "정적"및 "동적" 이 유형 시스템이 아닌 유형 검사를 보다 정확하게 설명한다고 지적하는 것이 맞습니다 . 실제로 언어가 정적으로 또는 동적으로 입력되었다고 말하는 것은 실제로 정확하지 않습니다. 오히려 언어에는 형식 시스템이 있으며 해당 언어를 구현하면 정적 검사, 동적 검사 또는 둘 다 또는 둘 다를 사용하여 형식 시스템을 적용 할 수 있습니다 (매우 매력적인 언어 구현은 아니지만).
이와 같이 정적 검사에 더 적합한 특정 유형 시스템 (또는 유형 시스템의 기능)이 있으며 동적 검사에 더 적합한 특정 유형 시스템 (또는 유형 시스템의 기능)이 있습니다. 예를 들어, 언어에서 프로그램의 텍스트에서 특정 값이 항상 정수 배열이어야한다고 지정할 수 있으면 해당 속성을 확인하기 위해 정적 검사기를 작성하는 것이 합리적입니다. 반대로, 언어에 하위 유형이 있고 다운 캐스팅을 허용하는 경우 런타임에 다운 캐스트의 유효성을 확인하는 것이 합리적이지만 컴파일 타임에는 그렇게하기가 매우 어렵습니다.
내가 정말 내 트윗을 의미하는 것은 언어 구현의 대부분이 수행 단순히이다 일부 동적 타입 검사의 양을. 또는 대부분의 언어에는 정적으로 확인하기 어려운 (아직 불가능하지는 않지만) 일부 기능이 있습니다. 다운 캐스팅이 한 예입니다. 다른 예로는 산술 오버플로, 배열 범위 검사 및 null 검사가 있습니다. 이러한 상황 중 일부는 상황에 따라 정적으로 검사 할 수 있지만 대체로 런타임시 검사를 수행하지 않는 언어 구현을 찾기가 어려울 것입니다.
이것은 나쁜 것이 아닙니다. 우리의 언어로 적용 할 흥미로운 속성이 많으며 정적으로 확인하는 방법을 모른다는 것이 관찰에 불과합니다. "정적 유형"과 "동적 유형"과 같은 차이점은 일부 사람들이 생각하는 것만 큼 명확하지 않다는 것을 상기시킵니다. :)
마지막으로, "강한"과 "약한"이라는 용어는 프로그래밍 언어 리서치 커뮤니티에서 실제로 사용되지 않으며 실제로 일관된 의미를 갖지 않습니다. 일반적으로, 누군가가 언어에 "강력한 타이핑"이 있고 다른 언어에 "약한 타이핑"이 있다고 말하면, 그들이 가장 좋아하는 언어 ( "강력한 타이핑"이있는 언어)가 언어를 방해한다고 말하는 것입니다. 다른 언어 ( "약한 타이핑"이있는 언어)가 그렇지 않거나 반대로 자신이 좋아하는 언어 ( "약한 타이핑"이있는 언어)가 다른 언어 ( "강력한 입력"을 가진 사람은 그렇지 않습니다.
그래 정적 유형 언어로 속성 백을 가질 수 있습니다. 구문은 끔찍하지만 동시에 동적으로 유형이 지정된 시스템의 모든 단점을 얻게됩니다. 따라서 컴파일러가 C #과 같은 더 좋은 구문을 사용할 수 없다면 실제로 어떤 이점도 없습니다 dynamic
.
또한 C에서도 그렇게 쉽게 할 수 있습니다.
다른 답변에 대한 반응으로 사람들은 강한 / 약한 타이핑으로 정적 / 동적 타이핑을 착각하고 있다고 생각합니다. 동적 타이핑은 런타임시 데이터 구조를 변경하고 코드에 필요한 데이터를 사용할 수있는 코드에 관한 것입니다. 이것을 오리 타이핑 이라고 합니다.
리플렉션은 기존 데이터의 구조를 변경할 수 없기 때문에 리플렉션을 언급하는 것은 전체 이야기를 말하지 않습니다. C, C ++, Java 또는 C #에서 클래스 또는 구조에 새 필드를 추가 할 수 없습니다. 동적 언어에서는 기존 클래스에 새 필드 또는 속성을 추가하는 것이 가능할뿐만 아니라 실제로는 일반적입니다.
예를 들어 Python-to-C 컴파일러 인 Cython을 보십시오 . 정적 C 코드를 작성하지만 유형 시스템은 여전히 동적 특성을 유지합니다. C는 정적으로 입력 된 언어이지만 Python에서 동적 입력을 지원할 수 있습니다.
ExpandoObject
는 JavaScript 또는 Ruby와는 달리 옵트 인 프로세스이지만 C #에서 버전 4부터 수행 할 수 있습니다 . 그래도 오리 타이핑 (개발자의 99 %가 "동적 유형"이라고 말할 때 실제로 의미하는 것)과 반사는 전혀 같은 것이 아니라는 점이 매우 중요합니다.
True
"이 미친 객체는 내가 정의하고있는 클래스의 인스턴스"라고 말하기 위해 반환 할 수있는 마술 방법을 가지고 있음)을위한 고리를 가지고 있습니다 . OCaml은 내가 이해하는 한이 기능을 가지고 있지만 실제로는 모른다.
동적 언어는 정적 언어 입니다. 일반적으로 "동적 타이핑"이라고하는 것은 실제로 정적 타이핑의 특별한 경우입니다. 하나의 유형 만 사용하도록 제한 한 경우입니다. 생각의 실험으로 만 사용하여 Java 또는 C #에서 프로그램 작성 상상 Object
변수 / 필드 / 매개 변수와 아래로 캐스팅 호출하기 전에 즉시 어떤 방법을. 파이썬이나 자바 스크립트와 같은 언어를 "유니 타입"이라고 부르는 것이 더 정확합니다. (이 주장은 Java 또는 C # 프로그램이 많은 하위 유형을 사용한다는 점을 고려하면 많은 사람들을 혼란스럽게하거나 혼동시킬 수 있지만 평균 OOP 언어가 유형과 클래스를 병합하기 때문입니다. 자세한 내용은 블로그 게시물을 읽으십시오.)
C조차도 "동적"타이핑이 있습니다. 포인터를 void
(메모리가 나를 위해 제공하는 경우) 포인터로 캐스트 char
하고 다시 되돌릴 수 있습니다. 또한 런타임 검사는 없습니다. 당신이 잘못되면 정의되지 않은 행동을 즐기십시오!
String foo = (String) bar
그것이 bar
실제로 a를 의미하는 것은 아니라고 말합니다 String
. 런타임에 확실히 알 수 있으므로 캐스트가 "정적으로"수행되는 방법을 알 수 없습니다.
dynamic
개체를 사용해야합니다 . object
...에 속성을 추가하려고 하면 할 수 없습니다.
정적 및 동적 입력의 차이는 경우 컴파일 시간 대 실행 시간 : 값의 형식을 체크한다. 값에 유형이 있는 언어 (예 : Java 객체)에서는 언어가 실제로 정적 타이핑을 선호하는 경우에도 항상 동적 타이핑을 사용할 수 있습니다. 다음은 동적으로 유형이 지정된 메소드가있는 Java의 예입니다.
void horribleJava(List untypedList) {
for (Object o : untypedList)
((SpecificType) o).frobnicate();
}
런타임에 각 항목의 유형을 확인하는 방법에 주목하십시오. 동일한 정적으로 형식화 된 방법은 다음과 같습니다.
void goodJava(List<SpecificType> typedList) {
for (SpecificType o : typedList) {
o.forbnicate();
}
}
C에서 값 (특히 포인터)은 런타임 동안 유형을 유지하지 않습니다. 모든 포인터는 a와 같습니다 void *
. 대신 변수 와 표현식에는 유형이 있습니다. 동적 타이핑을 달성하려면 타입 정보를 직접 전달해야합니다 (예 : 구조체의 필드).
frobnicate
대해 먼저 알지 않고 는 메소드를 호출 할 수 없습니다 SpecificType
.
dynamic
키워드). 정적 을 컴파일 타임에 , 동적 을 런타임에 동일시 하는 것은 대부분 물을 흐릿하게 만듭니다.
[1,2].Add([3,4])
얻을 [1,2,3,4]
, [1,2,[3,4]]
또는 [4,6]
?
Add
배열에 수용하는 메소드 가 없기 때문에 실패해야 합니다. 그러한 메소드는 모호하기 때문입니다. 오리 타이핑은 이해하기 쉬운 유형과 기능을 작성하는 데있어서 변명하지 않습니다.
정적 대 동적 입력은 기본적으로 유형을 확인하는 방법을 나타냅니다. 정적 유형 지정은 다양한 변수 또는 표현식 유형의 검증이 실제 코드 (일반적으로 컴파일러에 의해)를 기반으로 확인되는 반면 동적 유형 시스템에서는이 검증이 런타임 환경에서 런타임시에만 수행됨을 의미합니다.
텍스트가 참조하고 있다고 생각하는 것은 실제로 유형을 정적으로 확인하더라도 런타임에 동적으로 확인된다는 것입니다. Java Reflection을 올바르게 언급했습니다. 리플렉션은 런타임에서만 발생하며 JVM (Java Runtime Environment)은 리플렉션을 사용할 때 실제로 유형 확인을 수행합니다. 이는 기본적으로 동적 유형 확인을 의미합니다.