基本上,我想知道是否存在此代码无效的语言,因为即使counter
和distance
都是int
,它们代表不兼容的类型 in现实世界:
#include <stdio.h>
typedef int counter;
typedef int distance;
int main() {
counter pies = 1;
distance lengthOfBiscuit = 4;
printf("total pies: %d\n", pies + lengthOfBiscuit);
return 0;
}
编译没有警告“gcc -pedantic -Wall”和我尝试过的所有其他语言。似乎不允许意外添加计数器和距离是个好主意,那么语言支持在哪里?
(顺便提一下,引发这个问题的现实例子是用PHP和Python开发的web开发工具 - 我试图制作“HTML-escaped string”,“SQL-escaped string”和“raw dangerous user input”不兼容,但我能看到的最好的是这里建议的应用程序匈牙利表示法 - &gt; http://www.joelonsoftware.com/articles/Wrong.html&lt; - 并且仍然依赖于人工检查(“错误的代码看起来错误”)而不是编译器支持( “错误的代码 错误”))
答案 0 :(得分:1)
Haskell可以做到这一点,使用GeneralizedNewtypeDeriving,您可以将包装值视为基础事物,同时只暴露您需要的内容:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype Counter = Counter Int deriving Num
newtype Distance = Distance Int deriving Num
main :: IO ()
main = print $ Counter 1 + Distance 2
现在你收到了错误:
Add.hs:6:28:
Couldn't match expected type ‘Counter’ with actual type ‘Distance’
In the second argument of ‘(+)’, namely ‘Distance 2’
In the second argument of ‘($)’, namely ‘Counter 1 + Distance 2’
您仍然可以使用“强制”“强制”基础数据类型,或者明确地展开Ints。
我应该补充一点,任何具有“真实”类型的语言都应该能够做到这一点。
答案 1 :(得分:0)
您可以在成员变量中创建包含未定义类型的对象,并定义对该类型有意义的操作(即使是以函数的形式)(例如,LEngth将定义“plus”,允许添加到另一个长度,但是角度)。
这种方法的一个缺点是你必须为你关心的每个底层类型创建一个包装器,并为每个合理的组合定义适当的操作,这可能是乏味的并且可能容易出错。
在C ++中,您可以查看对{{3}}的BOOST支持。给出的示例主要是针对物理尺寸而设计的,但我认为您也可以将其适应其他许多尺寸。
答案 2 :(得分:0)
在Ada中,您可以使用相同的表示形式,但仍然是不同的类型。在C或C ++中,什么是“强类型定义”(如果它存在的话)。
在你的情况下,你可以做
type counter is new Integer;
type distance is new Integer;
创建两个行为类似整数的新类型,但不能混合。