Scala 类型定义和重写

Scala 类型定义和重写,scala,Scala,我是Scala的新手,我项目的一部分以以下设计结束 trait StringService { def length(s: String): Int def vowels(s: String): Int } 这些方法被用作 def processStrings(operation: String => Int) = {...} 像processStrings(ss.length)这样的调用工作正常。现在我想抽象一下 这些方法的类型 type StringFuction = St

我是Scala的新手,我项目的一部分以以下设计结束

trait StringService {
  def length(s: String): Int
  def vowels(s: String): Int
}
这些方法被用作

def processStrings(operation: String => Int) = {...}
processStrings(ss.length)
这样的调用工作正常。现在我想抽象一下 这些方法的类型

type StringFuction = String => Int
问题是像这样的实现

override def length(s: String): Int = { ... }
不再有效。当然,我可以和你一起去

override def length: StringFunction = { (s: String) => ... }
但这似乎有点不对劲。
正确的方法是什么?如果这不是真正的Scala方法,请随意建议不同的设计。

好的,有不同的方法可以做到这一点,具体取决于您希望使用类型别名的目的。例如:

type StringFunction = String => Int
trait Foo { def foo(s: String) = ???  }
class Bar extends Foo {
    def foo(s: String) = s.length
}

def foobar(f: StringFunction)(s) = f(s)

foobar(new Bar().foo)("bar")
这也有效:

type StringFunction = String => Int
trait Foo { def foo: StringFunction  = ???  }
class Bar extends Foo {
    override def foo = _.length
}


def foobar(f: StringFunction)(s) = f(s)
foobar(new Bar().foo)("bar")
严格地说,这些构造不同:在第一种情况下,
Foo.Foo
是一个方法,它接受一个字符串参数并返回一个Int。 在第二种情况下,它是一个方法,不带参数,返回lambda函数,带字符串参数,返回Int


不过,这种差异相当微妙。在某些特定情况下,它确实很重要,但通常可以忽略。

根据您使用类型别名的目的,有不同的方法可以做到这一点。例如:

type StringFunction = String => Int
trait Foo { def foo(s: String) = ???  }
class Bar extends Foo {
    def foo(s: String) = s.length
}

def foobar(f: StringFunction)(s) = f(s)

foobar(new Bar().foo)("bar")
这也有效:

type StringFunction = String => Int
trait Foo { def foo: StringFunction  = ???  }
class Bar extends Foo {
    override def foo = _.length
}


def foobar(f: StringFunction)(s) = f(s)
foobar(new Bar().foo)("bar")
严格地说,这些构造不同:在第一种情况下,
Foo.Foo
是一个方法,它接受一个字符串参数并返回一个Int。 在第二种情况下,它是一个方法,不带参数,返回lambda函数,带字符串参数,返回Int


不过,这种差异相当微妙。在某些特定情况下,它确实很重要,但通常可以忽略。

您最初的实现仍然有效。你为什么不这么认为?你有错误吗?不知道你的意思。类似于
override-def-length(s:String)=s.length的实现会导致错误“方法长度不覆盖任何内容”。
override-def-length:StringFunction=uu.length
工作正常,但我不喜欢它,原因是我不理解。尽管这是推荐的方法,我还是会接受的。没有完整的代码,不清楚什么是方法
length
被覆盖的。我可以用完整的代码给出一个更好的答案。您最初的实现仍然有效。你为什么不这么认为?你有错误吗?不知道你的意思。类似于
override-def-length(s:String)=s.length的实现会导致错误“方法长度不覆盖任何内容”。
override-def-length:StringFunction=uu.length
工作正常,但我不喜欢它,原因是我不理解。尽管这是推荐的方法,我还是会接受的。没有完整的代码,不清楚什么是方法
length
被覆盖的。我可以用完整的代码给出更好的答案。是的,Scala可以推断方法
foo
属于
StringFunction
类型。但是我想在trait中显式地使用类型。我怎样才能做到这一点?方法
foo
实际上不是
StringFunction
类型。函数和方法之间有一个微妙的区别,我在最后一段中试图解释。您可以将其定义为
def foo:StringFunction=?
val foo:StringFunction=???
来创建类型为
StringFunction
的成员,如我的第二个代码片段所示。与其他方法相比,这可能对您没有什么好处。“因为我不明白的原因而不喜欢它”听起来并不是一个好的工程推理;)谢谢,迪玛。我理解这件事。我只是希望Scala有一个神奇的功能,可以在幕后将一个方法转换为lambda。在第一个示例中,调用
foobar
需要神奇的eta扩展才能将
foo
作为函数值传递。@deepdown这正是上面指出的情况。是的,Scala可以推断方法
foo
属于
StringFunction
类型。但是我想在trait中显式地使用类型。我怎样才能做到这一点?方法
foo
实际上不是
StringFunction
类型。函数和方法之间有一个微妙的区别,我在最后一段中试图解释。您可以将其定义为
def foo:StringFunction=?
val foo:StringFunction=???
来创建类型为
StringFunction
的成员,如我的第二个代码片段所示。与其他方法相比,这可能对您没有什么好处。“因为我不明白的原因而不喜欢它”听起来并不是一个好的工程推理;)谢谢,迪玛。我理解这件事。我只是希望Scala有一个神奇的功能,可以在幕后将一个方法转换为lambda。在第一个示例中,调用
foobar
需要神奇的eta扩展,才能将
foo
作为函数值传递。@deepdown这正是上面所指出的情况。