[language-agnostic] 타입 안전이란 무엇입니까?

“유형 안전”이란 무엇입니까?



답변

형식 안전성은 컴파일러가 컴파일하는 동안 형식의 유효성을 검사하고 변수에 잘못된 형식을 할당하려고하면 오류를 발생시킵니다.

몇 가지 간단한 예 :

// Fails, Trying to put an integer in a string
String one = 1;
// Also fails.
int foo = "bar";

명시적인 형식을 전달하기 때문에 메서드 인수에도 적용됩니다.

int AddTwoNumbers(int a, int b)
{
    return a + b;
}

내가 그것을 사용하여 전화하려고하면 :

int Sum = AddTwoNumbers(5, "5");

문자열 ( “5”)을 전달하고 있고 정수를 기대하기 때문에 컴파일러에서 오류가 발생합니다.

자바 스크립트와 같이 느슨하게 입력 된 언어로 다음을 수행 할 수 있습니다.

function AddTwoNumbers(a, b)
{
    return a + b;
}

내가 이것을 이렇게 부르면 :

Sum = AddTwoNumbers(5, "5");

Javascript는 5를 문자열로 자동 변환하고 “55”를 반환합니다. 이는 문자열 연결에 + 기호를 사용하는 자바 스크립트 때문입니다. 형식을 인식하려면 다음과 같은 작업을 수행해야합니다.

function AddTwoNumbers(a, b)
{
    return Number(a) + Number(b);
}

또는 아마도 :

function AddOnlyTwoNumbers(a, b)
{
    if (isNaN(a) || isNaN(b))
        return false;
    return Number(a) + Number(b);
}

내가 이것을 이렇게 부르면 :

Sum = AddTwoNumbers(5, " dogs");

Javascript는 5를 문자열로 자동 변환하고 추가하여 “5 개”를 반환합니다.

모든 동적 언어가 자바 스크립트만큼 용서하는 것은 아닙니다 (사실 동적 언어가 느슨한 유형의 언어를 의미하지는 않습니다 (Python 참조)). 이들 중 일부는 실제로 유효하지 않은 유형 캐스팅에서 런타임 오류를 발생시킵니다.

편리하지만 쉽게 놓칠 수있는 많은 오류가 발생하며 실행중인 프로그램을 테스트해야만 식별 할 수 있습니다. 개인적으로, 나는 실수를 저지른 경우 컴파일러에게 알려주기를 선호합니다.

이제 C #으로 돌아가서

C #은 covariance 라는 언어 기능을 지원합니다. 이는 기본적으로 하위 유형을 기본 유형으로 대체하고 오류를 발생시키지 않을 수 있음을 의미합니다.

 public class Foo : Bar
 {
 }

여기에서 Bar를 서브 클래스로 만드는 새 클래스 (Foo)를 만들었습니다. 이제 메소드를 작성할 수 있습니다.

 void DoSomething(Bar myBar)

그리고 Foo 또는 Bar를 인수로 사용하여 호출하면 오류없이 작동합니다. 이것은 C #이 Bar의 모든 하위 클래스가 Bar의 인터페이스를 구현한다는 것을 알고 있기 때문에 작동합니다.

그러나 그 반대는 할 수 없습니다.

void DoSomething(Foo myFoo)

이 상황에서 컴파일러가 Bar가 Foo의 인터페이스를 구현한다는 것을 알지 못하므로 Bar를이 메소드에 전달할 수 없습니다. 자식 클래스는 부모 클래스와 크게 다를 수 있기 때문입니다.

물론, 이제는 원래 질문의 범위를 넘어서고 있지만 모든 좋은 점을 알고 있습니다. 🙂


답변

타입 안전성을 정적 / 동적 타이핑 또는 강력 / 약한 타이핑과 혼동해서는 안됩니다.

형식 안전 언어는 데이터에서 실행할 수있는 유일한 작업이 데이터 형식에 의해 용인되는 언어입니다. 즉, 데이터가 유형 X이고 Xoperation을 지원하지 않으면 y언어에서 실행할 수 없습니다 y(X).

이 정의는 이것이 체크 될 때 규칙을 설정하지 않습니다 . 일반적으로 예외를 통해 컴파일 타임 (정적 타이핑) 또는 런타임 (동적 타이핑) 일 수 있습니다. 일부 정적으로 입력 된 언어의 하나 개의 유형에서 다른 캐스트 데이터를 허용하고, 캐스트의 유효성이 런타임 (당신이 캐스팅하려고하는 상상에서 점검해야합니다 : 그것은 모두의 비트 수 없다 ObjectA를 Consumer컴파일러는 더있다 – 그것이 수용 가능한지 아닌지를 아는 방법).

타입 안전은 반드시 강력하게 타입을 의미하는 것은 아니며, 일부 언어는 약한 타입이지만 악명 높은 타입은 안전합니다. 예를 들어, 자바 스크립트를 보자. 형식 시스템은 약하지만 여전히 엄격하게 정의되어있다. 데이터를 자동으로 캐스팅 할 수 있지만 (예 : 문자열을 int로) 잘 정의 된 규칙 내에서 가능합니다. Javascript 프로그램이 정의되지 않은 방식으로 작동하는 경우는 없으며, 영리한 사람이라면 (잘 모르겠습니다) Javascript 코드를 읽을 때 발생할 일을 예측할 수 있어야합니다.

형식이 안전하지 않은 프로그래밍 언어의 예는 C입니다. 배열 범위 외부에서 배열 값을 읽거나 쓰면 사양에 따라 정의되지 않은 동작 이 있습니다 . 일어날 일을 예측하는 것은 불가능합니다. C는 타입 시스템을 가지고 있지만 타입 안전하지 않은 언어입니다.


답변

형식 안전성은 컴파일 시간 제약 조건이 아니라 런타임 제약 조건입니다. 이 모든 시간이 지나도 더 명확 해집니다.

유형 안전과 관련된 두 가지 주요 문제가 있습니다. 메모리 ** 및 데이터 유형 (해당 작업 포함).

기억**

A는 char일반적으로 문자 당 1 바이트 또는 8 개 비트를 요구 (16 개 비트를 필요로 언어, 자바 및 C # 저장소 유니 코드 문자에 따라 다름). 는 int4 바이트 또는 32 비트 (통상) 필요로한다.

시각적으로 :

char: |-|-|-|-|-|-|-|-|

int : |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

타입 안전 언어는 런타임에 int를 char에 삽입 할 수 없습니다 (이는 일종의 클래스 캐스트 또는 메모리 부족 예외를 발생시켜야 함). 그러나 안전하지 않은 유형의 언어에서는 기존 데이터를 더 인접한 3 바이트의 메모리에 덮어 씁니다.

int >> char:

|-|-|-|-|-|-|-|-| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?|

위의 경우 오른쪽의 3 바이트를 덮어 쓰므로 예측 가능한 char 값을 얻을 것으로 예상되는 해당 메모리에 대한 포인터 (예 : 3 개의 연속 문자)는 이제 가비지가됩니다. 이로 인해 undefined프로그램에서 동작 이 발생 합니다 (또는 요즘 OS가 메모리를 할당하는 방식에 따라 다른 프로그램에서 더 악화 될 수 있습니다).

** 이 첫 번째 문제는 기술적으로 데이터 형식에 관한 것이 아니지만 형식 안전 언어는 기본적으로이를 해결하며 메모리 할당이 어떻게 보이는지 알지 못하는 사람들에게 문제를 시각적으로 설명합니다.

데이터 형식

보다 미묘하고 직접적인 유형 문제는 두 데이터 유형이 동일한 메모리 할당을 사용하는 것입니다. 정수와 부호없는 정수를 취하십시오. 둘 다 32 비트입니다. (char [4]와 int 일 수는 있지만, 가장 일반적인 문제는 uint와 int입니다.)

|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

안전하지 않은 타입의 언어는 프로그래머가 32 비트의 적절하게 할당 된 범위를 참조 할 수있게하지만, 부호없는 int의 값을 int의 공간으로 읽어 들일 때 (또는 그 반대로), 우리는 다시 undefined동작을합니다. 뱅킹 프로그램에서 발생할 수있는 문제를 상상해보십시오.

“Dude! 나는 30 달러를 초과 인출했고 이제 $ 65,506가 남았습니다!”

… ‘물론 은행 프로그램은 훨씬 더 큰 데이터 유형을 사용합니다. 😉 LOL!

다른 사람들이 이미 지적했듯이 다음 문제는 유형에 대한 계산 작업입니다. 그것은 이미 충분히 다루어졌습니다.

속도 대 안전

오늘날 대부분의 프로그래머는 C 또는 C ++과 같은 것을 사용하지 않는 한 그러한 것에 대해 걱정할 필요가 없습니다. 두 언어 모두 프로그래머가 위험을 최소화하려는 최선의 노력에도 불구하고 프로그래머가 런타임시 유형 안전을 쉽게 위반할 수 있습니다 (직접 메모리 참조). 그러나 이것은 모두 나쁜 것은 아닙니다.

이러한 언어가 계산 속도가 빠른 이유 중 하나는 Java와 같은 런타임 작업 중에 형식 호환성을 확인하여 부담을주지 않기 때문입니다. 그들은 개발자가 문자열과 정수를 함께 추가하지 않는 좋은 합리적 존재라고 가정하며, 이에 대해 개발자에게는 속도 / 효율이 보상됩니다.


답변

여기에 많은 답변이 타입 안전성과 정적 타이핑 및 동적 타이핑을 혼동합니다. 스몰 토크와 같이 동적으로 유형이 지정된 언어도 유형에 안전합니다.

짧은 대답 : 작업이 정의되지 않은 동작을 유발하지 않으면 언어는 유형 안전으로 간주됩니다. 자동 변환은 때때로 잘 정의되지만 예기치 않은 / 직관적이지 않은 동작으로 이어질 수 있으므로 언어를 엄격하게 입력 하는 데 필요한 명시 적 유형 변환 요구 사항을 고려하는 사람들이 많습니다 .


답변

‘type-safe’인 프로그래밍 언어는 다음을 의미합니다.

  1. 초기화되지 않은 변수를 읽을 수 없습니다
  2. 범위를 벗어난 배열은 색인 할 수 없습니다
  3. 확인되지 않은 유형의 캐스트를 수행 할 수 없습니다

답변

comp sci 전공이 아닌 교양 전공의 설명 :

사람들이 언어 또는 언어 기능이 유형 안전하다고 말하면, 언어가 정수가 아닌 무언가를 정수를 기대하는 논리에 전달하는 것을 방지하는 데 도움이된다는 의미입니다.

예를 들어 C #에서 함수를 다음과 같이 정의합니다.

 void foo(int arg)

그런 다음 컴파일러는이 작업을 수행하지 못하게합니다.

  // call foo
  foo("hello world")

다른 언어에서는 컴파일러가 나를 멈추지 않거나 (또는 ​​컴파일러가 없습니다 …) 문자열이 논리에 전달되면 잘못된 것이 발생할 수 있습니다.

타입 안전 언어는 “컴파일 시간”에 더 많이 잡으려고합니다.

“123”과 같은 문자열이 있고 int처럼 조작하려면 문자열을 int로 변환하거나 int가있을 때 더 많은 코드를 작성해야합니다. 123 같은 “답은 123″같은 메시지에 사용하려면 문자열로 변환 / 캐스팅하기 위해 더 많은 코드를 작성해야합니다.


답변

더 나은 이해를 위해 아래 안전 비디오 (C #) 및 NOT 형식 안전 언어 (javascript)의 코드를 보여주는 아래 비디오를 시청하십시오.

http://www.youtube.com/watch?v=Rlw_njQhkxw

이제 긴 텍스트입니다.

유형 안전은 유형 오류를 방지하는 것을 의미합니다. 한 유형의 데이터 유형이 다른 유형에 알 수 없을 때 유형 오류가 발생하여 원하지 않는 결과가 발생합니다.

예를 들어 JavaScript는 형식이 안전한 언어가 아닙니다. 아래 코드에서 “num”은 숫자 변수이고 “str”은 문자열입니다. Javascript를 사용하면“num + str”을 수행 할 수 있습니다. 이제 GUESS는 산술 또는 연결을 수행합니다.

이제 아래 코드의 결과는 “55”이지만 중요한 점은 어떤 종류의 작업을 수행하는지 혼란이 발생한다는 것입니다.

이것은 자바 스크립트가 형식에 안전한 언어가 아니기 때문에 발생합니다. 제한없이 한 유형의 데이터를 다른 유형으로 설정할 수 있습니다.

<script>
var num = 5; // numeric
var str = "5"; // string
var z = num + str; // arthimetic or concat ????
alert(z); // displays  “55”
</script>

C #은 형식이 안전한 언어입니다. 한 데이터 유형을 다른 데이터 유형에 지정할 수 없습니다. 아래 코드는 다른 데이터 유형에서 “+”연산자를 허용하지 않습니다.

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