什么时候应该劝阻弱类型?在大型项目中不鼓励使用弱类型吗?如果左侧是像下面这样的强类型,那会是规则的例外吗?
int i = 5
string sz = i
sz = sz + "1"
i = sz
是否有任何语言支持与上述类似的语法?告诉我更多关于弱类型和相关情况的利弊。
什么时候应该劝阻弱类型?在大型项目中不鼓励使用弱类型吗?如果左侧是像下面这样的强类型,那会是规则的例外吗?
int i = 5
string sz = i
sz = sz + "1"
i = sz
是否有任何语言支持与上述类似的语法?告诉我更多关于弱类型和相关情况的利弊。
我认为您将“弱类型”与“动态类型”混淆了。
术语“弱类型”意味着“非强类型”,这意味着允许内存位置的值与其类型指示的值不同。
C 是弱类型语言的一个例子。它允许编写这样的代码:
typedef struct
{
int x;
int y;
} FooBar;
FooBar foo;
char * pStr = &foo;
pStr[0] = 'H';
pStr[1] = 'i';
pStr[2] = '\0';
也就是说,它允许将 FooBar 实例视为一个字符数组。
在强类型语言中,这是不允许的。要么会生成编译器错误,要么会抛出运行时异常,但在任何时候,FooBar 内存地址都不会包含不是有效 FooBar 的数据。
C#、Java、Lisp、Java Script 和 Ruby 是不允许此类事情的语言示例。它们是强类型的。
其中一些语言是“静态类型的”,这意味着变量类型是在编译时分配的,还有一些是“动态类型的”,这意味着变量类型直到运行时才知道。“静态与动态”和“弱与强”是正交问题。例如,Lisp 是一种“强动态类型”语言,而“C”是一种“弱静态类型语言”。
此外,正如其他人所指出的那样,“推断类型”和程序员指定的类型之间存在区别。C# 中的“var”关键字是类型推断的一个示例。然而,它仍然是一个静态类型的构造,因为编译器在编译时推断变量的类型,而不是在运行时。
所以,你的问题真正要问的是:
静态类型、动态类型、弱类型、强类型、推断静态类型和用户指定静态类型的相对优缺点是什么。
我在下面提供所有这些的答案:
静态类型
静态类型有 3 个主要好处:
由于静态类型提供的额外信息,在静态类型语言中,诸如智能和重构之类的用户体验和准确性得到了极大的改善。如果您键入“a”。在代码编辑器中并且“a”具有静态类型,那么编译器就知道“。”之后可能合法出现的所有内容。并因此可以向您显示准确的完成列表。在动态类型语言中支持某些场景是可能的,但它们受到的限制要大得多。
此外,在没有编译器错误的程序中,重构工具可以识别使用特定方法、变量或类型的每个地方。在动态类型语言中不可能做到这一点。
第二个好处有点争议。静态类型语言的支持者喜欢这样说。然而,静态类型语言的反对者认为,他们捕获的错误是微不足道的,无论如何他们都会被测试捕获。但是,您确实会预先收到诸如拼写错误的变量或方法名称之类的通知,这会很有帮助。
静态类型语言还可以实现更好的“数据流分析”,当与 Microsoft 的 SAL(或类似工具)之类的东西结合使用时,可以帮助发现潜在的安全问题。
最后,使用静态类型,编译器可以进行更多优化,因此可以生成更快的代码。
缺点:
静态类型的主要缺点是它限制了你可以做的事情。您可以使用无法使用静态类型语言编写的动态类型语言编写程序。Ruby on Rails 就是一个很好的例子。
动态打字
动态类型的最大优势在于它比静态类型强大得多。你可以用它做很多很酷的事情。
另一个是它需要更少的打字。您不必到处指定类型。
缺点:
动态类型有两个主要缺点:
强类型:
强类型的最大好处是安全性。强制执行强类型通常需要某种类型的运行时支持。如果一个程序可以证明类型安全,那么很多安全问题,比如缓冲区溢出,就会消失。
弱打字:
强类型的最大缺点和弱类型的最大好处是性能。
当您可以以任何您喜欢的方式访问内存时,您可以编写更快的代码。例如,数据库只需写出原始字节即可将对象交换到磁盘,而无需求助于“ISerializable”接口之类的东西。一个视频游戏可以通过在一个大缓冲区上运行一个 free 来丢弃与一个级别相关的所有数据,而不是为许多小对象运行析构函数。
能够做这些事情需要弱类型。
类型推断
类型推断允许静态类型的许多好处,而不需要太多的类型。
用户指定类型
有些人只是不喜欢类型推断,因为他们喜欢明确。这更像是一种风格。
弱类型化是一种语言简化的尝试。虽然这是一个有价值的目标,但弱类型是一个糟糕的解决方案。
COM Variants 中使用的弱类型是解决此问题的早期尝试,但它充满了危险,坦率地说,它带来的麻烦多于其价值。即使是忍受各种垃圾的 Visual Basic 程序员也正确地认为这是一个坏主意,并将 Microsoft 的 ETC(扩展类型转换)反向命名为 Evil Type Cast。
不要将推断类型与弱类型混淆。推断类型是在编译时从上下文推断的强类型。一个很好的例子是var
关键字,在 C# 中用于声明适合接收 LINQ 表达式值的变量。
相比之下,每次计算表达式时都会推断出弱类型。这在问题的示例代码中进行了说明。另一个例子是在 C 中使用无类型指针。非常方便,但也很麻烦。
推断类型解决了与弱类型相同的问题,但没有引入与弱类型相关的问题。因此,只要宿主语言可用,它就是一个首选的替代方案。
他们几乎总是应该气馁。我能想到的唯一类型的代码是需要一些指针巫术的低级代码。
为了回答你的问题,C 支持这样的代码(当然除了没有字符串类型),这听起来像是 PHP 或 Perl 会有的东西(但我可能完全错了)。
"
什么时候应该劝阻弱类型?在大型项目中不鼓励使用弱类型吗?如果左侧是像下面这样的强类型,那会是规则的例外吗?
int i = 5 string sz = i sz = sz + "1" i = sz
是否有任何语言支持与上述类似的语法?告诉我更多关于弱类型和相关情况的利弊。
"
也许您可以编写自己的库来做到这一点。
在 C++ 中,您可以使用称为“运算符重载”的东西,这意味着您可以将一种类型的变量声明为另一种类型的变量。这就是声明的原因:
[std::string str = "Hello World";][1]
具体来说,您将定义一个函数(其中变量的类型是 T 并且 B 是您想要将其设置为的类型)
工作,即使引号之间的任何文本都被解释为字符数组。
T& T::operator= ( const B s );
请注意,这是一个类的成员函数 另请注意,如果您想自由地使用它,您可能希望拥有某种反转此操作的函数 - 类似于
B& T::operator= ( const T s);
C++ 足够强大,可以让您创建一个通常为弱类型的对象,但如果您想将其视为纯弱类型,您将只想创建一个可用作任何原语的变量类型,并且只使用以下函数指向无效的指针。相信我,当它可用时,使用强类型编程要容易得多。
我个人更喜欢强类型,因为我不需要担心当我不知道变量是什么意思时会出现的错误。例如,如果我想编写一个函数来与一个人交谈——并且该函数使用了这个人的身高、体重、姓名、孩子的数量等——但是你给了我一个颜色,我会得到一个错误,因为你可以使用非常简单的算法并不能真正确定颜色中的大部分内容。
就弱类型的优点而言,如果您正在编写要在程序中运行的东西(即 Web 浏览器或 UNIX shell),您可能希望习惯于松散类型的编程。JavaScript 和 Shell 脚本是弱类型的。
我建议像汇编语言这样的编程语言是唯一的硬件级弱类型语言之一,但是我见过的汇编语言的风格根据分配的大小为每个变量附加一个类型,即 word、dword、qword .
我希望我给了你一个很好的解释,并没有在你嘴里放任何话。
弱类型本质上不如强类型健壮,因为你没有告诉机器确切地做什么 - 相反机器必须弄清楚你的意思。这通常工作得很好,但通常不清楚结果应该是什么。例如,一个字符串乘以浮点数是什么?
是否有任何语言支持与上述类似的语法?
Perl 允许您交替处理一些数字和字符串。例如,“5”+“1”会给你 6。这类事情的问题通常是很难避免歧义:“5”+1 应该是“51”还是“6”?Perl 通过为字符串连接使用单独的运算符并为数字加法保留 + 来解决此问题。
其他语言必须弄清楚您是要进行连接还是加法,以及(如果相关)结果将是什么类型或表示形式。
我进行了 ASP/VBScript 编码并使用没有“选项严格”的遗留代码,这允许弱类型。
这在很多时候都是地狱,尤其是在经验不足的程序员手中。我们得到所有愚蠢的错误需要很长时间才能诊断出来。
其中一个愚蠢的例子是这样的:
'Config
Dim pass
pass = "asdasd"
If NOT pass = Request("p") Then
Response.Write "login failed"
REsponse.End()
End If
到目前为止一切顺利,但如果用户将 pass 更改为整数密码,猜猜它不再起作用了,因为 int pass != string pass (from querystring)。我认为它应该可以工作,但我不记得确切的代码。
我讨厌弱打字,而不是愚蠢的调试会话,我可以花额外的时间来输入变量的确切类型。
简而言之,根据我的经验,尤其是在大型项目中,尤其是对于没有经验的开发人员来说,这只是麻烦。