我在解决重载时方法的方差方面遇到了一些问题.
虽然由于返回类型的协方差,这完美地起作用
class Bla
class Fasel extends Bla
trait Test[A] {
def tester(): Bla = new Bla
}
class FooTest[A](a: A) extends Test[A] {
override def tester(): Fasel = new Fasel
}
Run Code Online (Sandbox Code Playgroud)
即使函数在参数类型中是逆变的,这个也会失败.
class Bla
class Fasel extends Bla
trait Test[A] {
def tester(a: Fasel): Bla = new Bla
}
class FooTest[A](a: A) extends Test[A] {
override def tester(a: Bla): Fasel = new Fasel
}
Run Code Online (Sandbox Code Playgroud)
我在这里弄错了什么?有什么指针吗?
问候,raichoo
特定
scala> def method(x: Int) = x
method: (x: Int)Int
scala> val func = (x: Int) => x
func: Int => Int = <function1>
Run Code Online (Sandbox Code Playgroud)
请考虑以下代码:
scala> method _
res0: Int => Int = <function1>
scala> func(_)
res1: Int => Int = <function1>
scala> func _
res2: () => Int => Int = <function0>
Run Code Online (Sandbox Code Playgroud)
我可以理解,这res0是eta扩展,res1相当于lambda函数(x) => func(x).但我无法弄清楚输出res2.谁有人可以帮我解释一下?
这两个函数声明是否有效地不同?
如果没有,为什么他们有不同的toString值?
scala> def f: (Int) => Int = x=> x*x
f: (Int) => Int
scala> def f(x: Int) = x*x
f: (Int)Int
Run Code Online (Sandbox Code Playgroud) 从更复杂的程序简化:
scala> type T = (String) => String
defined type alias T
scala> def f(s: String) = s + " (parsed)"
f: (s: String)java.lang.String
scala> f _
res0: (String) => java.lang.String = <function1>
scala> def g(func: T) = func _
<console>:6: error: _ must follow method; cannot follow (String) => String
def g(func: T) = func _
^
Run Code Online (Sandbox Code Playgroud)
我真的不明白为什么这不起作用.一个方法和一些形式的东西之间的区别是什么(Type1, Type2 ...) => Type,以及什么是从这样的东西中获得部分功能的正确方法?
我最近参加了一个初学者Scala聚会,我们正在谈论方法和功能之间的区别(这里也进行了深入讨论).
例如:
scala> val one = 1
one: Int = 1
scala> val addOne = (x: Int) => x + 1
addOne: Int => Int = <function1>
Run Code Online (Sandbox Code Playgroud)
这表明val不仅可以具有整数类型,而且可以具有函数类型.我们可以在scala repl中看到类型:
scala> :type addOne
Int => Int
Run Code Online (Sandbox Code Playgroud)
我们还可以在对象和类中定义方法:
scala> object Foo {
| def timesTwo(op: Int) = op * 2
| }
defined module Foo
Run Code Online (Sandbox Code Playgroud)
虽然方法没有类型(但是具有类型签名),我们可以将其提升为函数以查看它是什么:
scala> :type Foo.timesTwo
<console>:9: error: missing arguments for method timesTwo in object Foo;
follow this method with `_' if you want to treat …Run Code Online (Sandbox Code Playgroud) Case类可以扩展特征并使用其字段实现它.
trait IWork {
def itWorks: String
}
case class Example(itWorks: String) extends IWork
Run Code Online (Sandbox Code Playgroud)
它编译并正常工作.你能解释一下,为什么不能编译?
trait IsAfter {
def after(test: Date): Boolean
}
case class Example2(after: Date => Boolean) extends IsAfter
Run Code Online (Sandbox Code Playgroud) 我已经阅读了Scala中方法和函数之间的差异以及许多关于方法和函数之间差异的文章.我感觉'方法'只是一个"命名函数",被定义为类,特征或对象中的方法."函数"表示这些文章中的"匿名函数"或"函数文字"或"函数对象".有关证据的信息可以在Scala中编程 http://www.artima.com/shop/programming_in_scala_2ed,第141页,第8.1节中找到,"定义函数的最常用方法是作为某个对象的成员.函数被称为方法."
但是,当我检查Scala语言参考http://www.scala-lang.org/docu/files/ScalaReference.pdf时,有一些概念,如命名方法.在页91,第6.20节中返回表达式:"返回表达式返回e必须出现在一些封闭的命名方法或函数的主体内." 您还可以在同一页面和其他位置找到术语"命名函数".
所以我的问题是,在Scala中,做方法,命名方法和命名函数是指同一个概念吗?你在哪里得到命名函数的定义?
在代码中List(1, 2).map(_ + 1),原始表达式_ + 1是一个命名方法,然后将该方法转换为函数.什么样的函数,匿名函数,函数对象,命名函数?
根据我的理解,Scala只有两种类型的函数:作为方法的命名函数; 一个函数文字的匿名函数.函数文字被编译成特征FunctionN的函数对象,以便在纯粹的面向对象的Scala世界中使用.
但是,对于常规命名的funciton /方法(如_ + 1上面的代码中),为什么Scala会将其转换为另一个函数对象?
Scala头版说
函数是一流的对象.用保证类型安全性来组合它们.在任何地方使用它们,传递给任何东西.
但我似乎无法val像Scala中的其他第一类对象一样存储函数.
scala> def myFunction = { println("hello world") }
myMethod: Unit
scala> myFunction
hello world
scala> val myVal = myFunction
hello world
myVal: Unit = ()
scala> myVal
scala>
Run Code Online (Sandbox Code Playgroud)
这样做的正确方法是什么?
我正在阅读这个页面,我在scala中遇到了这个函数定义:
def upper: String => String = _.toUpperCase
Run Code Online (Sandbox Code Playgroud)
尝试后,似乎它的工作方式与此相同:
def upper = (str: String) => str.toUpperCase()
Run Code Online (Sandbox Code Playgroud)
两个功能都一样吗?如果是这样,我如何阅读上述功能(第一个)?这种定义定义的方式有特定的名称吗?
scala ×10
function ×3
anonymous ×1
inheritance ×1
methods ×1
named ×1
overriding ×1
variance ×1