답변:
강력한 형식의 언어와 정적 형식의 언어의 차이점은 무엇입니까?
정적으로 유형이 지정된 언어에는 구현 (컴파일러 또는 인터프리터)에 의해 컴파일시 확인되는 유형 시스템이 있습니다. 유형 검사는 일부 프로그램을 거부하며 검사를 통과 한 프로그램에는 일반적으로 보증이 제공됩니다. 예를 들어, 컴파일러는 부동 소수점 숫자에 정수 산술 명령어를 사용하지 않도록 보장합니다.
전문 문헌에서 가장 널리 사용되는 정의는 "강력한 유형의"언어에서는 프로그래머가 유형 시스템에 의해 부과 된 제한 사항을 해결할 수 없다는 것입니다. . 이 용어는 거의 항상 정적으로 유형이 지정된 언어를 설명하는 데 사용됩니다.
정적 유형의 반대는 "동적 유형"입니다.
예를 들어, 동적으로 유형이 지정된 언어 인 Lua 는 문자열 유형, 숫자 유형 및 부울 유형을 갖습니다. 루아에서 모든 값은 정확히 하나의 유형에 속하지만 모든 동적 유형 언어에 필요한 것은 아닙니다. Lua에서는 두 개의 문자열을 연결할 수 있지만 문자열과 부울을 연결할 수는 없습니다.
"strongly typed"(강력한 유형)의 반대는 "약한 유형"이므로 유형 시스템을 해결할 수 있습니다. C는 포인터 유형이 캐스팅에 의해 다른 포인터 유형으로 변환 될 수 있기 때문에 약하게 형식화되지 않습니다. 파스칼은 강력하게 타이핑하기위한 것이었지만, 디자인에 대한 감독 (태그가없는 변형 레코드)은 타이핑 시스템에 허점을 도입했기 때문에 기술적으로는 타이핑이 약합니다. 실제로 강력한 형식의 언어의 예로는 CLU, Standard ML 및 Haskell이 있습니다. 표준 ML은 실제로 언어가 널리 배포 된 후 발견 된 유형 시스템의 허점을 제거하기 위해 몇 가지 수정을 거쳤습니다.
전반적으로, "강한"과 "약한"에 대해 이야기하는 것이 그렇게 유용하지 않은 것으로 밝혀졌습니다. 유형 시스템에 허점이 있는지 여부는 허점의 정확한 수와 특성보다 실제로 중요 할 가능성과 허점을 악용 한 결과입니다. 실제로, 그것은 전부 용어 "강한"과 "약"을 피하기 위해 최선 때문에,
아마추어는 종종 "정적"및 "동적"과 충돌합니다.
분명히 "약한 타이핑"은 암시 적 변환의 상대적 유병률이나 부재에 대해 이야기하기 위해 일부 사람들에 의해 사용됩니다.
전문가는 용어의 의미에 정확히 동의 할 수 없습니다.
전반적으로 청중에게 정보를 제공하거나 깨달을 가능성은 없습니다.
슬프게도 유형 시스템에있어서 "강한"및 "약한"은 보편적으로 합의 된 기술적 의미를 갖지 않는다는 것입니다. 유형 시스템의 상대적인 강도를 논의하려면 보증이 제공되고 제공되지 않는 것이 무엇인지 정확하게 논의하는 것이 좋습니다. 예를 들어, 좋은 질문은 "해당 유형의 생성자 중 하나를 호출하여 주어진 유형 (또는 클래스)의 모든 값이 생성 되었는가?"입니다. C에서 답은 '아니오'입니다. CLU, F # 및 Haskell에서는 그렇습니다. C ++의 경우 확실하지 않습니다. 알고 싶습니다.
반대로 정적 타이핑 은 프로그램이 실행되기 전에 확인되고 프로그램이 시작되기 전에 거부 될 수 있음을 의미합니다. 동적 유형 지정 은 실행 중에 값 유형을 확인 하며 잘못 입력하면 프로그램이 중지되거나 런타임시 오류를 표시 할 수 있습니다. 정적 타이핑의 주요 이유는 "동적 유형 오류"가있는 프로그램을 배제하기위한 것입니다.
하나는 다른 것을 의미합니까?
"강력한"이라는 단어가 실제로 의미하는 것은 아니기 때문에 pedantic 레벨에서는 아닙니다. 그러나 실제로 사람들은 거의 항상 두 가지 중 하나를 수행합니다.
"정적"및 "동적"을 의미하기 위해 "올바르지 않은" "강한"및 "약한"을 사용합니다.이 경우 "올바르지 않은" "강한 유형"및 "정적 유형"을 서로 바꾸어 사용하고 있습니다.
정적 유형 시스템의 특성을 비교하기 위해 "강한"및 "약한"을 사용합니다. 누군가가 "강한"또는 "약한"동적 유형 시스템에 대해 말하는 것을 듣는 것은 매우 드 rare니다. 실제로 모든 종류의 유형 시스템이없는 FORTH를 제외하고 유형 시스템을 파괴 할 수있는 동적 유형 언어를 생각할 수 없습니다. 정의에 따라 이러한 검사는 실행 엔진으로 처리되고 실행되기 전에 모든 작업이 정상 상태인지 검사됩니다.
어느 쪽이든, 사람이 "강하게 입력 된"언어를 호출하면 그 사람은 정적으로 입력 된 언어에 대해 이야기 할 가능성이 높습니다.
이것은 종종 잘못 이해되므로 정리해 보겠습니다.
정적 타입은 타입이 변수에 바인딩되는 곳 입니다. 컴파일 타임에 타입을 확인합니다.
동적 유형은 유형이 값에 바인딩되는 곳 입니다. 유형은 런타임에 확인됩니다.
예를 들어 Java에서는 다음과 같습니다.
String s = "abcd";
s
"영원히"될 것 String
입니다. 수명 동안 다른 String
s를 가리킬 수 있습니다 ( s
Java의 참조 이므로 ). null
값 이있을 수 있지만 결코 Integer
a 또는 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 (아마도 익숙하지 않은 경우 놀랍게도)는 그렇지 않습니다.
여기서 중요한 점은 정적 / 동적 축이 강한 / 약한 축과 독립적이라는 것입니다. 강한 타이핑과 약한 타이핑은 덜 명확하게 정의 될뿐만 아니라 강력하고 약한 의미가 정확히 무엇인지에 대한 실제 합의가 없기 때문에 사람들은 아마도 부분적으로 혼동합니다. 이러한 이유로 강한 / 약한 타이핑은 검은 색 또는 흰색이 아닌 회색 음영에 가깝습니다.
따라서 귀하의 질문에 대답하기 위해 : 이것이 가장 올바른 것을 보는 또 다른 방법 은 정적 입력이 컴파일 타임 유형 안전이고 강력한 입력이 런타임 유형 안전이라고 말하는 것입니다.
그 이유는 정적으로 유형이 지정된 언어의 변수에는 선언해야하며 컴파일시 확인할 수있는 유형이 있기 때문입니다. 강력한 형식의 언어에는 런타임에 형식이있는 값이 있으며 프로그래머가 동적 검사없이 형식 시스템을 파괴하기가 어렵습니다.
그러나 언어는 정적 / 강한, 정적 / 약한, 동적 / 강한 또는 동적 / 약한 언어 일 수 있음을 이해해야합니다.
"abc" + 123
A는 런타임 오류, 루비하지 컴파일 오류입니다. 컴파일 오류 인 경우 루비는 정적으로 입력됩니다.
둘 다 서로 다른 두 축의 극입니다.
강력하게 입력 하면 a가 한 유형에서 다른 유형으로 자동 변환되지 않습니다. 약한 유형은 반대입니다. Perl은 "123"
자동으로 int로 변환하여 숫자 컨텍스트 와 같은 문자열을 사용할 수 있습니다 123
. 파이썬과 같은 강력한 유형의 언어는이 작업을 수행하지 않습니다.
정적으로 유형이 지정 되면 컴파일러는 컴파일 타임에 각 변수의 유형을 알아냅니다. 동적 유형 언어는 런타임시 변수 유형 만 파악합니다.
강력한 유형은 유형 간 변환간에 제한이 있음을 의미합니다. 정적 유형은 유형이 동적이 아님을 의미합니다. 변수가 작성된 후에는 유형을 변경할 수 없습니다.
데이터 강제는 때때로 그것의 구문 설탕이기 때문에 약한 유형을 의미하지는 않습니다.
Java로 인해 위의 예가 약하게 입력되었습니다.
String s = "abc" + 123;
실제로 수행하기 때문에 약한 유형의 예제가 아닙니다.
String s = "abc" + new Integer(123).toString()
새 개체를 생성하는 경우 데이터 강제 변환도 약하게 입력되지 않습니다. Java는 약한 유형의 매우 나쁜 예입니다 (반사가 좋은 언어는 약한 유형이 아닐 것입니다). 언어의 런타임은 항상 유형이 무엇인지 알고 있기 때문에 예외는 기본 유형일 수 있습니다.
이것은 C와는 다릅니다. C는 약한 유형의 가장 좋은 예 중 하나입니다. 런타임은 4 바이트가 정수, 구조체, 포인터 또는 4 문자인지 전혀 모릅니다.
언어의 실행 시간은 실제로 약한 유형인지 아닌지 여부에 대한 정의입니다.
편집 : 추가로 생각하면 런타임이 런타임 시스템에서 모든 유형을 Restricted Typed 시스템으로 수정 할 필요는 없기 때문에 이것이 반드시 사실 일 필요는 없습니다. Haskell과 ML은 런타임에서 타입 정보를 생략 할 수있는 완벽한 정적 분석 기능을 가지고 있습니다.
위의 답변이 이미 제공되어 있습니다. 강한 대 주와 정적 대 동적 개념을 구별하려고합니다.
강력한 유형 : 한 유형에서 다른 유형으로 자동 변환되지 않습니다.
Go 또는 Python에서 강력한 유형의 언어 인 "2"+ 8은 "유형 강제"를 허용하지 않으므로 유형 오류가 발생합니다.
약하게 (느슨하게) 유형화 됨 : 자동으로 한 유형으로 다른 유형으로 변환됩니다 : JavaScript 또는 Perl과 같은 약한 유형의 언어는 오류를 발생시키지 않으며이 경우 JavaScript는 '28'이되고 perl은 10이됩니다.
펄 예제 :
my $a = "2" + 8;
print $a,"\n";
main.pl에 저장하고 실행 perl main.pl
하면 출력 10이 표시됩니다.
프로그래밍에서 프로그래머는 변수 유형을 확인하는 지점과 관련하여 정적 유형 지정 및 동적 유형 지정을 정의합니다. 정적 형식 언어는 컴파일 타임에 형식 검사가 수행되는 언어 인 반면 동적 형식 언어는 런타임에 형식 검사가 수행되는 언어입니다.
이것이 무엇을 의미합니까?
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
강력한 타이핑은 변수에 유형이 잘 정의되어 있고 다른 유형의 변수를 표현식에 결합하는 데 대한 엄격한 규칙이 있음을 의미합니다. 예를 들어 A가 정수이고 B가 부동 소수점 인 경우 A + B에 대한 엄격한 규칙은 A를 부동 소수점으로 변환하고 결과를 부동 소수점으로 반환하는 것일 수 있습니다. A가 정수이고 B가 문자열 인 경우 엄격한 규칙은 A + B가 유효하지 않을 수 있습니다.
정적 타이핑은 아마도 컴파일 타임에 유형이 할당되거나 컴파일되지 않은 언어에 해당하는 유형을 의미하며 프로그램 실행 중에는 변경할 수 없습니다.
이 분류는 상호 배타적이지 않으므로 실제로 자주 분류되기를 기대합니다. 많은 강력한 형식의 언어도 정적으로 형식이 지정됩니다.
그리고 아마도 '아마도'라는 단어를 사용할 때이 용어에 대한 보편적으로 인정되는 정의가 없기 때문입니다. 지금까지 답변에서 이미 보았 듯이.