在Scala中,如何对伴生对象执行编译时类型检查?
在许多语言中,但在Scala中不容易做到的一件事是: 定义原型“Super”,以便“Super”的所有实现都必须定义构造函数“create()” 我发现这个约束非常重要,并且能够在运行前发现很多问题。然而,这个特性在Java中只是部分实现(通过定义一个总是抛出错误的“抽象”静态方法),而在Scala中完全缺失(伴随对象与类完全分离,不能在原型中实现) 是否有宏或工具允许我这样做 更新很抱歉,我的问题缺少上下文和示例。下面是scala中的一个正式用例: 在项目A中,我们定义了一个可由所有子项目扩展的接口:在Scala中,如何对伴生对象执行编译时类型检查?,scala,compile-time,typechecking,Scala,Compile Time,Typechecking,在许多语言中,但在Scala中不容易做到的一件事是: 定义原型“Super”,以便“Super”的所有实现都必须定义构造函数“create()” 我发现这个约束非常重要,并且能够在运行前发现很多问题。然而,这个特性在Java中只是部分实现(通过定义一个总是抛出错误的“抽象”静态方法),而在Scala中完全缺失(伴随对象与类完全分离,不能在原型中实现) 是否有宏或工具允许我这样做 更新很抱歉,我的问题缺少上下文和示例。下面是scala中的一个正式用例: 在项目A中,我们定义了一个可由所有子项目扩展
trait AbstractFoo {}
此接口应始终具有默认的0参数生成器/构造函数,因此project a可以按需对其进行初始化,但是project a不知道每个构造函数的实现:
object AbstractFoo {
def default[T <: AbstractFoo: ClassTag](): T
}
必须满足:
trait FooBuilder[T <: AbstractFoo] {
def default(): T
}
object AbstractFoo {
implicit object Foo extends FooBuilder[Foo] {
def default() = {...}
}
def default[T <: AbstractFoo: FooBuilder](): T = {
implicitly[FooBuilder[T]].default
}
}
scala将引用类Foo的作用域,其中包括包含隐式值Foo的对象Foo,并最终找到0参数构造函数
我认为这个定义比在object FooBuilder下定义要好,因为您只能定义FooBuilder一次,因此它不太可扩展。你同意我的意见吗?如果是这样,你能修改一下你的答案吗?这样我就可以给你加分了。我不明白为什么一个
抽象类
甚至一个特质
都不允许这样做
abstract class DefineCreate{
def create(): Unit
}
case class Foo(one: Int)
object Foo extends DefineCreate{
def create(): Unit = { Console.out.println("side-effect") }
}
因此,我强制用户在所讨论的对象上创建create
方法,因为DefineCreate
的所有实现都必须这样做才能编译
更新以下评论
不必求助于宏之类的东西,就可以用类型类实现同样的功能:
trait Constructor[A]{
def create(): A
}
object Construct{
def create[A](implicit cr: Constructor[A]): A = cr.create()
}
它不会显式地强制伴随对象生成方法,但如果用户想要使用构造函数,它会强制用户生成类型类。创建[Foo]
模式。我不明白为什么抽象类
甚至特征
都不允许这样做
abstract class DefineCreate{
def create(): Unit
}
case class Foo(one: Int)
object Foo extends DefineCreate{
def create(): Unit = { Console.out.println("side-effect") }
}
因此,我强制用户在所讨论的对象上创建create
方法,因为DefineCreate
的所有实现都必须这样做才能编译
更新以下评论
不必求助于宏之类的东西,就可以用类型类实现同样的功能:
trait Constructor[A]{
def create(): A
}
object Construct{
def create[A](implicit cr: Constructor[A]): A = cr.create()
}
这并没有显式地强制伴随对象生成方法,但如果用户想要使用构造函数,它确实会强制用户生成type类。创建[Foo]
模式。我不认为Java中有“抽象”静态方法。静态方法是不能被重写的。Op是如此无知,但却如此确信他所说的,这有点可笑。。。我不知道他是不是在抱怨不,这是一个合理的问题(见@Wheaties回答中的评论)是的,OP不知道如何陈述他在问什么。请停止向下投票。根据您当前的界面,您需要这样调用它:AbstractFoo.default[ConcreteFoo]
。在这种情况下,我认为隐式类型类模式非常适合……我不认为“抽象”静态方法在Java中是一种东西。静态方法是不能被重写的。Op是如此无知,但却如此确信他所说的,这有点可笑。。。我不知道他是不是在抱怨不,这是一个合理的问题(见@Wheaties回答中的评论)是的,OP不知道如何陈述他在问什么。请停止向下投票。根据您当前的界面,您需要这样调用它:AbstractFoo.default[ConcreteFoo]
。在这种情况下,我认为隐式类型类模式非常适合……那么你怎么看1。要求所有Foo子类必须在其伴生对象中定义create()?2.仅通过类型信息类[Foo]查找函数Foo.create()?啊,现在我知道你在问什么了。你有这个用例吗?我不清楚您为什么需要它。第2点不是您在Scala中通常会做的事情。非常感谢所有的答案:)我应该很快重构我的问题,以避免更多误导。@tribbloid您的目标是什么?强制trait/接口的实现者拥有一个带有预定义参数集的“构造函数”?有一种构造特定类型对象的通用方法吗?还有别的吗?那你怎么看。要求所有Foo子类必须在其伴生对象中定义create()?2.仅通过类型信息类[Foo]查找函数Foo.create()?啊,现在我知道你在问什么了。你有这个用例吗?我不清楚您为什么需要它。第2点不是您在Scala中通常会做的事情。非常感谢所有的答案:)我应该很快重构我的问题,以避免更多误导。@tribbloid您的目标是什么?强制trait/接口的实现者拥有一个带有预定义参数集的“构造函数”?有一种构造特定类型对象的通用方法吗?还有别的吗?
trait Constructor[A]{
def create(): A
}
object Construct{
def create[A](implicit cr: Constructor[A]): A = cr.create()
}