不知道如何搜索这个问题的答案,但我想知道在 Java、C#、Scala 等编译语言中是否有办法......在错误使用 API 的情况下强制出现编译器错误。
假设您正在使用某种 API,并且您知道在调用其他方法 Y 之前需要调用特定的设置方法 X,是否可以进行设置以使编译器能够捕获错误并避免这样做所以在运行时?
这对于强制执行某些代码标准或修复损坏的 API 非常有用。不知道它是否可能。
不知道如何搜索这个问题的答案,但我想知道在 Java、C#、Scala 等编译语言中是否有办法......在错误使用 API 的情况下强制出现编译器错误。
假设您正在使用某种 API,并且您知道在调用其他方法 Y 之前需要调用特定的设置方法 X,是否可以进行设置以使编译器能够捕获错误并避免这样做所以在运行时?
这对于强制执行某些代码标准或修复损坏的 API 非常有用。不知道它是否可能。
通常,您不能在大多数静态语言中创建任意自定义编译时错误。有一些例外(例如#error
C 和 C++ 中的指令,但即便如此,预处理器也严格位于主编译之前,因此无济于事)。
但是,您可以利用专门设计用于在编译时捕获错误的语言功能:
要求按特定顺序调用方法对 API 使用者不友好,并且是高级语言中的代码异味。
一个简单的解决方案是公开一个以正确顺序执行这两个操作的方法。更一般地(例如,如果不必调用第二个方法),让第二个方法调用顶部的第一个方法。但大概您希望调用受 API 使用者的控制。
在这种情况下,重构你的代码,这样就不可能在不产生类型错误的情况下以错误的顺序调用方法。例如,假设您正在编写一个正则表达式库,其中必须在匹配之前编译正则表达式。在 Scala 中,重构:
class Regex(pattern : String) {
private[this] var compiled : Option[CompiledData] = None
def compile() {
// do stuff
this.compiled = ...
}
def search(s : String) : MatchResult = compiled match {
case Some(c) => ... // match the string
case None => throw new IllegalStateException("must compile regex first")
}
}
到
class Regex(pattern : String) {
def compile : CompiledRegex = {
// do stuff
CompiledRegex(...)
}
}
class CompiledRegex(c : CompiledData) {
def search(s : String) : MatchResult = {
... // match the string
}
}
由于该search
方法现在仅在 上可用CompiledRegex
,并且CompiledRegex
是通过调用来获得的,因此在通过编译正则表达式使该操作有效之前Regex.compile
不可能调用。search
此设置还有助于 API 使用者,因为如果用户需要一个类型的对象MatchResult
并且已经键入new Regex("[abc123]*")
,一个好的 IDE 可以自动完成或建议所需的方法.compile
;这在原始设置中是不可能的。
(在这个例子中,它也不再需要可变状态,这在 Scala 中经常被避免。)
作为替代解决方案,某些语言(我认为 D 和 C++11,虽然不是您列出的那些)支持静态断言。
NDepend(用于 .NET)或JArchitect(用于 java)等工具允许在 LINQ 查询上编写自定义代码规则,这些规则可以在分析时(在 IDE中或在构建过程时)发出警告或错误。例如,下面的 CQLinq 代码规则强制如果一个方法正在调用,它必须调用:MethodA()
MethodB()
warnif count > 0
from m in Application.Methods where
m.IsUsing("MyNamespace.MyClass.MyMethodA()") &&
!m.IsUsing("MyNamespace.MyClass.MyMethodB()")
select m
特定函数的使用在编译器操作之外的另一个层面上......因此我认为编译器不应该做那样的事情......
另一方面:编译器通常集成到 IDE 中……你为什么不把它也放到 IDE 模块中呢?... 大多数 IDE 允许预编译器操作 ...
您可以编写某种检查工具(基于 CodeDOM 或类似的东西)来测试特定功能的使用,并根据该检查结果,如果质量标准不匹配,则中止编译器运行......