在Scala中修改具有类型化特征的类
我最近一直在玩Scala,在使用解析器组合器时,我在扩展它们时遇到了一些问题。基本上,我想做的就是这样在Scala中修改具有类型化特征的类,scala,typetraits,parser-combinators,Scala,Typetraits,Parser Combinators,我最近一直在玩Scala,在使用解析器组合器时,我在扩展它们时遇到了一些问题。基本上,我想做的就是这样 import scala.util.parsing.combinator.RegexParsers abstract class Statement case object Foo extends Statement case object Bar extends Statement case object Baz extends Statement class Program(stat
import scala.util.parsing.combinator.RegexParsers
abstract class Statement
case object Foo extends Statement
case object Bar extends Statement
case object Baz extends Statement
class Program(statements: List[Statement])
class FooBarLanguageParser extends RegexParsers {
def program: Parser[Program] = rep(statement) ^^ (v => new Program(List() ++ v))
def statement: Parser[Statement] = foo|bar
def foo: Parser[Statement] = "foo" ^^ (_ => Foo)
def bar: Parser[Statement] = "bar" ^^ (_ => Bar)
}
trait BazStatement { this: FooBarLanguageParser =>
override def statement: Parser[Statement] = baz|this.statement // inifinite recursion
def baz: Parser[Statement] = "baz" ^^ (_ => Baz)
}
object Main {
def main(args: Array[String]) {
val normalFooBar = new FooBarLanguageParser()
val fooBarProgram = normalFooBar.parseAll(normalFooBar.program, "foo bar")
val extendedFooBar = new FooBarLanguageParser() with BazStatement
val extendedFooBarProgram = extendedFooBar.parseAll(extendedFooBar.program,
"foo bar baz")
println(fooBarProgram.successful)
println(extendedFooBarProgram.successful)
}
}
在这里,我想在BazStatement
中调用FooBarLanguageParser
的statement
方法,但是使用上面的代码,我递归地调用BazStatement
的方法,因此它无法正常工作
我已经看了周围的答案,我知道我可以扩展这个类并使用抽象重写,或者类似这样的想法,但我认为这在这里没有任何意义,因为BazStatement
确实是我想与我的基本解析器混合的附加功能。我绝对不想有一些随意的事情,比如
object StrangeInheritance extends BazStatement
在代码中授权
在Scala中有没有什么惯用的方法可以正确地实现这一点,或者我需要重新考虑一下应用程序的总体设计?使用super调用supertype的方法,也可以使用traits定义顶级抽象。这个运行正常:
import scala.util.parsing.combinator.RegexParsers
abstract class Statement
case object Foo extends Statement
case object Bar extends Statement
case object Baz extends Statement
class Program(statements: List[Statement])
trait FooBarLanguageParser extends RegexParsers {
def program: Parser[Program] = rep(statement) ^^ (v => new Program(List() ++ v))
def statement: Parser[Statement] = foo|bar
def foo: Parser[Statement] = "foo" ^^ (_ => Foo)
def bar: Parser[Statement] = "bar" ^^ (_ => Bar)
}
trait BazStatement extends FooBarLanguageParser {
override def statement: Parser[Statement] = baz| super.statement // inifinite recursion
def baz: Parser[Statement] = "baz" ^^ (_ => Baz)
}
object Main {
def main(args: Array[String]) {
val normalFooBar = new FooBarLanguageParser() {}
val fooBarProgram = normalFooBar.parseAll(normalFooBar.program, "foo bar")
val extendedFooBar = new FooBarLanguageParser() with BazStatement
val extendedFooBarProgram = extendedFooBar.parseAll(extendedFooBar.program,
"foo bar baz")
println(fooBarProgram.successful)
println(extendedFooBarProgram.successful)
}
}
对不起,我迟了答复。关于这段代码的一点是,
object FooBar extensed BazStatement
将完美地工作,我将能够使用FooBarLanguageParser
中的所有方法,我发现这有点像我希望BazStatement
成为我的FooBarLanguageParser
的一个单独的额外功能。实际上混合了(traits)是非常惯用的scala方式,它提供了特别的模块化。如果您想提供一种将一组谨慎行为组合到一个运行时对象中的方法,我认为这是默认选项。您可能是对的,实际上mixin在这里可能不起作用,因为很难以可扩展的方式设计顶级解析器。也许在一些实用特性中有一组通用规则,然后在这个“通用规则”特性的帮助下构建“具体的”底层解析器,会是比尝试使用继承更好的选择。谢谢你的回答。我想我会像你说的那样,用顶级特性定义一般规则和一些具体实现。