강력한 형식의 언어와 정적 형식의 언어의 차이점은 무엇입니까?


답변:


542

강력한 형식의 언어와 정적 형식의 언어의 차이점은 무엇입니까?

정적으로 유형이 지정된 언어에는 구현 (컴파일러 또는 인터프리터)에 의해 컴파일시 확인되는 유형 시스템이 있습니다. 유형 검사는 일부 프로그램을 거부하며 검사를 통과 한 프로그램에는 일반적으로 보증이 제공됩니다. 예를 들어, 컴파일러는 부동 소수점 숫자에 정수 산술 명령어를 사용하지 않도록 보장합니다.

전문 문헌에서 가장 널리 사용되는 정의는 "강력한 유형의"언어에서는 프로그래머가 유형 시스템에 의해 부과 된 제한 사항을 해결할 수 없다는 것입니다. . 이 용어는 거의 항상 정적으로 유형이 지정된 언어를 설명하는 데 사용됩니다.

정적 대 동적

정적 유형의 반대는 "동적 유형"입니다.

  1. 런타임에 사용되는 값은 유형으로 분류됩니다.
  2. 이러한 값을 사용하는 방법에는 제한이 있습니다.
  3. 이러한 제한을 위반하면 위반이 (동적) 유형 오류로보고됩니다.

예를 들어, 동적으로 유형이 지정된 언어 인 Lua 는 문자열 유형, 숫자 유형 및 부울 유형을 갖습니다. 루아에서 모든 값은 정확히 하나의 유형에 속하지만 모든 동적 유형 언어에 필요한 것은 아닙니다. Lua에서는 두 개의 문자열을 연결할 수 있지만 문자열과 부울을 연결할 수는 없습니다.

강한 대 약

"strongly typed"(강력한 유형)의 반대는 "약한 유형"이므로 유형 시스템을 해결할 수 있습니다. C는 포인터 유형이 캐스팅에 의해 다른 포인터 유형으로 변환 될 수 있기 때문에 약하게 형식화되지 않습니다. 파스칼은 강력하게 타이핑하기위한 것이었지만, 디자인에 대한 감독 (태그가없는 변형 레코드)은 타이핑 시스템에 허점을 도입했기 때문에 기술적으로는 타이핑이 약합니다. 실제로 강력한 형식의 언어의 예로는 CLU, Standard ML 및 Haskell이 있습니다. 표준 ML은 실제로 언어가 널리 배포 된 후 발견 된 유형 시스템의 허점을 제거하기 위해 몇 가지 수정을 거쳤습니다.

진짜 무슨 일이야?

전반적으로, "강한"과 "약한"에 대해 이야기하는 것이 그렇게 유용하지 않은 것으로 밝혀졌습니다. 유형 시스템에 허점이 있는지 여부는 허점의 정확한 수와 특성보다 실제로 중요 할 가능성과 허점을 악용 한 결과입니다. 실제로, 그것은 전부 용어 "강한"과 "약"을 피하기 위해 최선 때문에,

  • 아마추어는 종종 "정적"및 "동적"과 충돌합니다.

  • 분명히 "약한 타이핑"은 암시 적 변환의 상대적 유병률이나 부재에 대해 이야기하기 위해 일부 사람들에 의해 사용됩니다.

  • 전문가는 용어의 의미에 정확히 동의 할 수 없습니다.

  • 전반적으로 청중에게 정보를 제공하거나 깨달을 가능성은 없습니다.

슬프게도 유형 시스템에있어서 "강한"및 "약한"은 보편적으로 합의 된 기술적 의미를 갖지 않는다는 것입니다. 유형 시스템의 상대적인 강도를 논의하려면 보증이 제공되고 제공되지 않는 것이 무엇인지 정확하게 논의하는 것이 좋습니다. 예를 들어, 좋은 질문은 "해당 유형의 생성자 중 하나를 호출하여 주어진 유형 (또는 클래스)의 모든 값이 생성 되었는가?"입니다. C에서 답은 '아니오'입니다. CLU, F # 및 Haskell에서는 그렇습니다. C ++의 경우 확실하지 않습니다. 알고 싶습니다.

반대로 정적 타이핑 은 프로그램이 실행되기 전에 확인되고 프로그램이 시작되기 전에 거부 될 수 있음을 의미합니다. 동적 유형 지정 은 실행 중에 유형을 확인 하며 잘못 입력하면 프로그램이 중지되거나 런타임시 오류를 표시 할 수 있습니다. 정적 타이핑의 주요 이유는 "동적 유형 오류"가있는 프로그램을 배제하기위한 것입니다.

하나는 다른 것을 의미합니까?

"강력한"이라는 단어가 실제로 의미하는 것은 아니기 때문에 pedantic 레벨에서는 아닙니다. 그러나 실제로 사람들은 거의 항상 두 가지 중 하나를 수행합니다.

  • "정적"및 "동적"을 의미하기 위해 "올바르지 않은" "강한"및 "약한"을 사용합니다.이 경우 "올바르지 않은" "강한 유형"및 "정적 유형"을 서로 바꾸어 사용하고 있습니다.

  • 정적 유형 시스템의 특성을 비교하기 위해 "강한"및 "약한"을 사용합니다. 누군가가 "강한"또는 "약한"동적 유형 시스템에 대해 말하는 것을 듣는 것은 매우 드 rare니다. 실제로 모든 종류의 유형 시스템이없는 FORTH를 제외하고 유형 시스템을 파괴 할 수있는 동적 유형 언어를 생각할 수 없습니다. 정의에 따라 이러한 검사는 실행 엔진으로 처리되고 실행되기 전에 모든 작업이 정상 상태인지 검사됩니다.

어느 쪽이든, 사람이 "강하게 입력 된"언어를 호출하면 그 사람은 정적으로 입력 된 언어에 대해 이야기 할 가능성이 높습니다.


3
@Adam : 분명히 반박하기에 충분히 옳지 않습니다. :) Cletus의 답변에 너무 많은 오해가 포함되어 있기 때문에 (내가 최악의 것을 편집 했음에도 불구하고) 한 음절로 모든 것을 철자해야한다는 느낌이 들었습니다.
Norman Ramsey

1
글쎄, 난 당신을 upvoted :) "컴파일"이라는 단어조차도 동적 언어를 실행하는 오늘날의 VM에서 분명하지 않습니다. 기술적으로 Java와 C #은 모두 두 번 (JIT) 컴파일되며 둘 다 유형 분석을 수행합니다. .NET vm에서 실행되는 Javascript와 같은 언어는 VM으로 인해 형식이 더 안전 할 수 있습니다.
Adam Gent

2
너무 혼란 스러워요! 좋아, 경기장의 위대한 검투사, 나 같은 가난한 영혼은 다음과 같은 간단한 이해로 갈 수 있습니까? 1. 정적 : 값은 컴파일 타임 동안 유형과 연관되고 런타임은 아닙니다. 2. 동적 : 값은 런타임 동안 유형과 연관되므로 런타임 중에 값 유형이 변경 될 수 있으므로 유형 캐스팅 관련 문제가 발생하기 쉽습니다. 런타임 중. 3. 강 / 약 : 잊어 버리세요! 이것들은 기술적 인 용어가 아니며 단지 나쁜 명칭입니다. 그것은 어떤 맥락에서 이야기하고 있는지에 달려 있습니다. 이 간단한 이해로 인생을 살아갈 수 있습니까? :(
Saurabh Patil

"지정된 유형 (또는 클래스)의 모든 값이 해당 유형의 생성자 중 하나를 호출하여 생성되었음을 보증합니까?" C에서 답은 '아니오'입니다. 누군가 C에서 이런 상황이 발생하는 예를 제공 할 수 있습니까? 구조체에 포인터를 캐스팅하는 것과 관련이 있다고 생각합니까?
corazza

강력하고 약한 타이핑 : 그러한 분류는 없습니다.
Raúl

248

이것은 종종 잘못 이해되므로 정리해 보겠습니다.

정적 / 동적 입력

정적 타입은 타입이 변수에 바인딩되는 곳 입니다. 컴파일 타임에 타입을 확인합니다.

동적 유형은 유형이 값에 바인딩되는 곳 입니다. 유형은 런타임에 확인됩니다.

예를 들어 Java에서는 다음과 같습니다.

String s = "abcd";

s"영원히"될 것 String입니다. 수명 동안 다른 Strings를 가리킬 수 있습니다 ( sJava의 참조 이므로 ). null값 이있을 수 있지만 결코 Integera 또는 a를 참조하지는 않습니다 List. 정적 입력입니다.

PHP에서 :

$s = "abcd";          // $s is a string
$s = 123;             // $s is now an integer
$s = array(1, 2, 3);  // $s is now an array
$s = new DOMDocument; // $s is an instance of the DOMDocument class

다이나믹 한 타이핑입니다.

강하고 약한 타이핑

(알림 편집!)

강력한 타이핑 은 널리 동의 된 의미가없는 문구입니다. 정적 타이핑 이외의 다른 의미로이 용어를 사용하는 대부분의 프로그래머는이 용어를 사용하여 컴파일러에 의해 적용되는 유형 규칙이 있음을 의미합니다. 예를 들어, CLU에는 유형이 제공 한 생성자를 사용하지 않고 클라이언트 코드가 추상 유형의 값을 작성할 수없는 강력한 유형 시스템이 있습니다. C는 다소 강력한 유형 시스템을 가지고 있지만 프로그램이 항상 한 포인터 유형의 값을 다른 포인터 유형의 값으로 캐스트 할 수 있기 때문에 어느 정도 "전복"될 수 있습니다. 예를 들어 C에서는 값을 가져 와서 malloc()쾌적하게 캐스팅 할 수 FILE*있으며 컴파일러는 멈추지 않으려 고하거나 피하고있는 일을 경고합니다.

(원래의 대답은 "런타임에서 유형을 변경하지 않는"값에 대해 말했습니다. 저는 많은 언어 디자이너와 컴파일러 작성자를 알고 있으며 유형에 대한 매우 고급 연구를 제외하고 런타임에 유형을 변경하는 값에 대해 이야기 한 사람을 알지 못했습니다. "강력한 업데이트 문제"라고 알려진 시스템).

타이핑이 약하다 는 것은 컴파일러가 타이핑 규칙을 시행하지 않거나 시행을 쉽게 파괴 할 수 있음을 의미합니다.

이 답변의 원본은 암시 적 변환 (때로는 "암시 적 프로모션"이라고도 함)을 사용 하여 약한 타이핑을 혼란스럽게 만들었습니다 . 예를 들어, Java에서 :

String s = "abc" + 123; // "abc123";

이 코드는 암시 적 승격의 예입니다. 123은에 연결하기 전에 암시 적으로 문자열로 변환됩니다 "abc". Java 컴파일러가 해당 코드를 다음과 같이 다시 작성한다고 주장 할 수 있습니다.

String s = "abc" + new Integer(123).toString();

고전적인 PHP "시작"문제를 고려하십시오.

if (strpos('abcdef', 'abc') == false) {
  // not found
}

여기서 오류 strpos()는 일치 색인을 0으로 반환 한다는 것입니다. 0은 부울로 강제 적용 false되므로 조건은 실제로 참입니다. 솔루션은 암시 적 변환을 피하기 위해 ===대신 사용하는 것입니다 ==.

이 예제는 암시 적 변환과 동적 타이핑의 조합이 프로그래머를 어떻게 타락시킬 수 있는지 보여줍니다.

Ruby와 비교해보십시오 :

val = "abc" + 123

Ruby에서 객체 123이 메소드에 전달되기 때문에 암시 적으로 변환 되지 않기 때문에 런타임 오류 +입니다. Ruby에서 프로그래머는 변환을 명시 적으로 작성해야합니다.

val = "abc" + 123.to_s

PHP와 Ruby를 비교하는 것이 좋은 예입니다. 둘 다 동적으로 입력되는 언어이지만 PHP에는 많은 암시 적 변환이 있으며 Ruby (아마도 익숙하지 않은 경우 놀랍게도)는 그렇지 않습니다.

정적 / 동적 vs 강 / 약

여기서 중요한 점은 정적 / 동적 축이 강한 / 약한 축과 독립적이라는 것입니다. 강한 타이핑과 약한 타이핑은 덜 명확하게 정의 될뿐만 아니라 강력하고 약한 의미가 정확히 무엇인지에 대한 실제 합의가 없기 때문에 사람들은 아마도 부분적으로 혼동합니다. 이러한 이유로 강한 / 약한 타이핑은 검은 색 또는 흰색이 아닌 회색 음영에 가깝습니다.

따라서 귀하의 질문에 대답하기 위해 : 이것이 가장 올바른 것을 보는 또 다른 방법 은 정적 입력이 컴파일 타임 유형 안전이고 강력한 입력이 런타임 유형 안전이라고 말하는 것입니다.

그 이유는 정적으로 유형이 지정된 언어의 변수에는 선언해야하며 컴파일시 확인할 수있는 유형이 있기 때문입니다. 강력한 형식의 언어에는 런타임에 형식이있는 값이 있으며 프로그래머가 동적 검사없이 형식 시스템을 파괴하기가 어렵습니다.

그러나 언어는 정적 / 강한, 정적 / 약한, 동적 / 강한 또는 동적 / 약한 언어 일 수 있음을 이해해야합니다.


$ s가 정수 또는 문자열이라고 말하는 대신, 유형이 변수 $ s가 아닌 "abcd"또는 1234와 연관되어 있다고 말하면 더 좋을 것입니다.
Srinivas Reddy Thatiparthy

명확한 예를 가진 훌륭한 답변. 그러나 나는 왜 사람들이 쌍둥이 쌍의 개념으로 강력하고 정적 인 것을 요구하는지에 대한 혼란을 완전히 해결하지 못한다고 생각합니다. 예를 들어 OP의 "정적 타이핑이 묵시적으로 타이핑합니까?" 당신의 대답은 그들의 독립성을 강조합니다. 왜 강점을 정적 상태로 유지하는지에 대한 설명을 계속하기 위해 Norman Ramsey의 이전 답변은 매우 좋습니다 : stackoverflow.com/questions/376611/…
JasDev

1
"abc" + 123A는 런타임 오류, 루비하지 컴파일 오류입니다. 컴파일 오류 인 경우 루비는 정적으로 입력됩니다.
sepp2k

약한 타이핑 예제는 개선해야하지만 (내 대답 참조) 그렇지 않으면 멋진 형식입니다.
Adam Gent

내 opion에서 강한 대 약한 typgin은 다음과 같습니다. Strong : "c"+ True = 런타임 오류 또는 컴파일 시간 오류. 약한 : "c"+ True = "b"또는 "d"모든 것이 원시 바이트로 취급되기 때문입니다. 강력 함 : C #, Ruby, C ++ 약점 : 어셈블리, C (암시 적 무효 포인터로 인해)
Jonathan Allen

17

둘 다 서로 다른 두 축의 극입니다.

  • 강력한 유형과 약한 유형
  • 정적 유형과 동적 유형

강력하게 입력 하면 a가 한 유형에서 다른 유형으로 자동 변환되지 않습니다. 약한 유형은 반대입니다. Perl은 "123"자동으로 int로 변환하여 숫자 컨텍스트 와 같은 문자열을 사용할 수 있습니다 123. 파이썬과 같은 강력한 유형의 언어는이 작업을 수행하지 않습니다.

정적으로 유형이 지정 되면 컴파일러는 컴파일 타임에 각 변수의 유형을 알아냅니다. 동적 유형 언어는 런타임시 변수 유형 만 파악합니다.


6
동의하지 않아야합니다. 강력한 형식의 언어는 런타임에 형식이 무엇인지 아는 언어입니다. 약한 유형의 언어는 어셈블리를 좋아하지 않는 언어입니다. 귀하의 예는 "암시 적 vs 명시 적 전환"의 세 번째 축에 있습니다.
Jonathan Allen

1
실제로는 Jonathan에 동의하지만 정적 분석을 완료하고 캐스팅을 허용하지 않는 경우 런타임에 형식을 강요하기 위해 런타임에 사용 가능한 형식을 가질 필요는 없습니다. (편집 된 답변 참조).
Adam Gent

1
파이썬은 동적으로 타이핑되고 강력하게 타이핑 된 언어의 예입니다
MaRoBet

13

강력한 유형은 유형 간 변환간에 제한이 있음을 의미합니다. 정적 유형은 유형이 동적이 아님을 의미합니다. 변수가 작성된 후에는 유형을 변경할 수 없습니다.


이를 증명하려면 : 강력한 형식의 언어에서는 "5"== 5를 비교하여 사실이 될 수 없습니다. 문자열은 정수가 아닙니다. 내 기억이 제공된다면, 가장 현대적인 스크립팅 언어는 강력하게 동적으로 입력됩니다. 그러나 Tcl / Tk는 형식이 잘못되었습니다. 모든 것을 문자열로 취급 할 수 있습니다.
리틀 바비 테이블

바비는 약한 유형의 언어에서 "5"== 5는 0x35 == 0x05로 읽습니다. 즉, 모든 것이 원시 바이트로 취급됩니다.
Jonathan Allen

나는 둘 다에 동의하지 않습니다. 루아를 가져 가라. "5"== 5를 비교하면 false를 반환하지만 "5"+ 0으로 이동하면 빠른 변환을 수행 할 수 있습니다.
RCIX

12

데이터 강제는 때때로 그것의 구문 설탕이기 때문에 약한 유형을 의미하지는 않습니다.

Java로 인해 위의 예가 약하게 입력되었습니다.

String s = "abc" + 123;

실제로 수행하기 때문에 약한 유형의 예제가 아닙니다.

String s = "abc" + new Integer(123).toString()

새 개체를 생성하는 경우 데이터 강제 변환도 약하게 입력되지 않습니다. Java는 약한 유형의 매우 나쁜 예입니다 (반사가 좋은 언어는 약한 유형이 아닐 것입니다). 언어의 런타임은 항상 유형이 무엇인지 알고 있기 때문에 예외는 기본 유형일 수 있습니다.

이것은 C와는 다릅니다. C는 약한 유형의 가장 좋은 예 중 하나입니다. 런타임은 4 바이트가 정수, 구조체, 포인터 또는 4 문자인지 전혀 모릅니다.

언어의 실행 시간은 실제로 약한 유형인지 아닌지 여부에 대한 정의입니다.

편집 : 추가로 생각하면 런타임이 런타임 시스템에서 모든 유형을 Restricted Typed 시스템으로 수정 할 필요는 없기 때문에 이것이 반드시 사실 일 필요는 없습니다. Haskell과 ML은 런타임에서 타입 정보를 생략 할 수있는 완벽한 정적 분석 기능을 가지고 있습니다.


잘 알려지지 않은 경우 B가 더 좋습니다.
Tom Hawtin-tackline

Javascript는 또한 약한 유형이지만 유형이 너무 적고 실제로 새로운 유형을 생성 할 수 없기 때문입니다.
Adam Gent

10

위의 답변이 이미 제공되어 있습니다. 강한 대 주와 정적 대 동적 개념을 구별하려고합니다.

Strongly typed vs Weakly typed는 무엇입니까?

강력한 유형 : 한 유형에서 다른 유형으로 자동 변환되지 않습니다.

Go 또는 Python에서 강력한 유형의 언어 인 "2"+ 8은 "유형 강제"를 허용하지 않으므로 유형 오류가 발생합니다.

약하게 (느슨하게) 유형화 됨 : 자동으로 한 유형으로 다른 유형으로 변환됩니다 : JavaScript 또는 Perl과 같은 약한 유형의 언어는 오류를 발생시키지 않으며이 경우 JavaScript는 '28'이되고 perl은 10이됩니다.

펄 예제 :

my $a = "2" + 8;
print $a,"\n";

main.pl에 저장하고 실행 perl main.pl하면 출력 10이 표시됩니다.

정적 VS 동적 유형이란 무엇입니까?

프로그래밍에서 프로그래머는 변수 유형을 확인하는 지점과 관련하여 정적 유형 지정 및 동적 유형 지정을 정의합니다. 정적 형식 언어는 컴파일 타임에 형식 검사가 수행되는 언어 인 반면 동적 형식 언어는 런타임에 형식 검사가 수행되는 언어입니다.

  • 정적 : 런타임 전에 확인 된 유형
  • 동적 : 실행 중 즉시 확인 된 유형

이것이 무엇을 의미합니까?

Go에서는 런타임 전에 입력 된 검사를 수행합니다 (정적 검사). 즉, 실행중인 코드를 번역하고 유형 검사 할뿐만 아니라 모든 코드를 스캔하고 코드가 실행되기 전에 유형 오류가 발생합니다. 예를 들어

package main

import "fmt"

func foo(a int) {
    if (a > 0) {
        fmt.Println("I am feeling lucky (maybe).")
    } else {
        fmt.Println("2" + 8)
    }
}

func main() {
    foo(2)
}

이 파일을 main.go에 저장하고 실행하면 컴파일 실패 메시지가 나타납니다.

go run main.go
# command-line-arguments
./main.go:9:25: cannot convert "2" (type untyped string) to type int
./main.go:9:25: invalid operation: "2" + 8 (mismatched types string and int)

그러나이 경우는 Python에 유효하지 않습니다. 예를 들어 다음 코드 블록은 첫 번째 foo (2) 호출에 대해 실행되고 두 번째 foo (0) 호출에 대해서는 실패합니다. 파이썬은 동적으로 유형이 지정되어 있기 때문에 실행중인 코드 만 번역하고 유형을 확인합니다. else 블록은 foo (2)에 대해 실행되지 않으므로 "2"+ 8은 전혀 보지 않으며 foo (0) 호출에 대해서는 해당 블록을 실행하려고 시도했지만 실패했습니다.

def foo(a):
    if a > 0:
        print 'I am feeling lucky.'
    else:
        print "2" + 8
foo(2)
foo(0)

다음과 같은 결과가 나타납니다.

python main.py
I am feeling lucky.
Traceback (most recent call last):
  File "pyth.py", line 7, in <module>
    foo(0)
  File "pyth.py", line 5, in foo
    print "2" + 8
TypeError: cannot concatenate 'str' and 'int' objects

8

하나는 다른 것을 의미하지 않습니다. 언어를 정적으로 유형화한다는 것은 모든 변수의 유형이 컴파일 타임에 알려 지거나 추론됨을 의미합니다.

강력하게 형식화 된 언어는 다른으로 한 유형을 사용할 수 없습니다. C는 약한 유형의 언어이며 강력한 유형의 언어가 허용하지 않는 좋은 예입니다. C에서는 잘못된 유형의 데이터 요소를 전달할 수 있으며 불평하지 않습니다. 강력하게 입력 된 언어에서는 할 수 없습니다.


7

강력한 타이핑은 변수에 유형이 잘 정의되어 있고 다른 유형의 변수를 표현식에 결합하는 데 대한 엄격한 규칙이 있음을 의미합니다. 예를 들어 A가 정수이고 B가 부동 소수점 인 경우 A + B에 대한 엄격한 규칙은 A를 부동 소수점으로 변환하고 결과를 부동 소수점으로 반환하는 것일 수 있습니다. A가 정수이고 B가 문자열 인 경우 엄격한 규칙은 A + B가 유효하지 않을 수 있습니다.

정적 타이핑은 아마도 컴파일 타임에 유형이 할당되거나 컴파일되지 않은 언어에 해당하는 유형을 의미하며 프로그램 실행 중에는 변경할 수 없습니다.

이 분류는 상호 배타적이지 않으므로 실제로 자주 분류되기를 기대합니다. 많은 강력한 형식의 언어도 정적으로 형식이 지정됩니다.

그리고 아마도 '아마도'라는 단어를 사용할 때이 용어에 대한 보편적으로 인정되는 정의가 없기 때문입니다. 지금까지 답변에서 이미 보았 듯이.

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