一个类型安全的语言是否需要静态类型?

3

我希望你能帮我理解什么是类型安全。在动态类型语言中,类型检查是在运行时进行的。例如,如果我运行以下PHP代码:

<?php
class MyClass
{ 
}

// Create a MyClass instance
$mc = new MyClass();

// Create an int variable
$i = 1234;

// Add $mc and $i
$result = $mc + $i;
?>

我会因为+运算符不支持MyClass数据类型而出现错误。所以基本上类型检查是在运行时执行的。
类型安全是指无论是在编译时还是在运行时进行类型检查,还是指必须仅在编译时执行类型检查,因此每个变量必须显式地给出数据类型(如C、Pascal、Java等)。

针对这种特定情况,存在某种类型安全性,但如果你说function x() { $i = 0; if (true) { $i = "bla"; } return $i; },就没有了。 - Royal Bg
顺便提一下,你的示例将导致1235,因此也没有安全性。 - Royal Bg
@Royal Bg 如果一种语言在运行时执行类型检查,并在发现类型错误时停止程序,那么这样的语言被称为类型安全语言吗? - user4407915
很可能不是这样。在一些论文中,您可能会发现这些语言被称为有限类型安全语言或在有限上下文中类型安全。对我来说,如果您可以将其隐藏在if()块中,则没有类型安全性。 - Royal Bg
C并不完全是类型安全的。如果它是,那么它就不会有太多未定义的行为了。C#不一定是静态、强类型的,但它被认为是类型安全的。但是,如果你不想让它成为类型安全的,它也不必成为类型安全的。Java被设计成类型安全的,但仍然有一系列的异常需要抛出/处理,以防类型系统让你失望(BigDecimal.divideNullPointerException,...)。 - Elias Van Ootegem
2个回答

6
“类型安全”通常指“内存类型安全”,也就是说,不能将包含一种类型的内存视为另一种类型。
按照这个定义,大多数高级语言,包括动态类型语言,都是类型安全的,因为任何尝试错误使用类型都会在它们中引起错误(编译时或运行时)。
因此,类型安全主要是低级语言的问题,特别是C和C++。而这些问题通常涉及指针或转换(例如,在C++中使用reinterpret_cast)。
C#是一个介于两个组之间的有趣案例:默认情况下它是类型安全的,但你可以使用unsafe关键字关闭部分代码的类型安全性(通常是为了性能或交互操作)。
但如果将类型安全与静态类型结合起来,并不意味着必须编写类型。许多静态类型安全的语言,特别是函数式语言或受其启发的语言,使用类型推断。这意味着编译器可以自己找出变量的类型,基于所分配的内容,所以你不必输入它。这方面的例子包括C++中的auto关键字和C#中的var

1
类型安全不是问题,因为它可以防止您犯错,并帮助您确保知道自己在做什么(PHP 就像使用您不了解的食材进行烹饪)。在我个人看来,类型安全语言中的类型推断并不好,因为它会让您过于轻易地失去对变量类型的概览。哎呀,您不这样认为吗?那么几十年后需要扩展或更改您的代码块的人就会这样认为。 - Martin Braun

3
答案是否定的。Python是一种动态但强类型语言的例子:
>>> "foo" + 42
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects

Haxe是一个编译时类型安全的语言的例子,但仍然不需要静态声明类型。
class Test {
    static function main() {
        trace(10 * Test.some());
    }

    static function some() {
        return "foo";
    }
}

> Build failure
> Test.hx:3: characters 19-30 : String should be Int

这是通过类型推断完成的。

Haxe怎么能在编译时知道一个变量的数据类型,如果它们没有静态声明,我只能在“if”块里更改数据类型,从而防止Haxe在编译时知道数据类型将是什么。 - user4407915
@Steve:在某个时候,你必须将某些东西分配给一个变量,这就是Haxe推断其类型的地方。你也可以像Python一样声明一个变量为动态的。请参见http://old.haxe.org/ref/type_infer。 - georg
我的意思是如果 Haxe 在编译时执行类型检查,并且还支持在不明确指定数据类型的情况下创建变量,这意味着我可以创建一个 if 块,在运行时更改变量的数据类型,而后该变量将用于不支持此新更改的数据类型的语句。例如:var i = 123; if (something) i = new MyClass(); var result = i + otherVariable; - user4407915
所以这就像变量是静态声明的,但实际上没有指定数据类型! - user4407915
在这种情况下,我认为这个说法是不正确的:“编译时类型安全的语言,但仍然不需要静态声明类型”,我认为一个编译时类型安全的语言不能允许在运行时更改数据类型。 - user4407915
@Steve:它们可以,有点像:C++有特殊的转换,例如(reinterpret_castdynamic_caststatic_cast)。C#也有动态类型(var foo = 123;int foo = 123;相同),而C++11的auto关键字也允许静态声明而不指定实际类型。在C中,类型仅在编译时存在,因此您可以很容易地-有点像-在运行时更改变量的数据类型:int i = 20; some_func_expecting_char_ptr(&i); <-- 在函数中,i将被用作char *,也可以使用union - Elias Van Ootegem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接