当我将包装器定义为值类(扩展AnyVal)时:
class Wrapper(val string: String) extends AnyVal
def wrapperHolder(w: Wrapper): {def wrapper: Wrapper} = new {
def wrapper: Wrapper = w
}
Run Code Online (Sandbox Code Playgroud)
我对于wrapperHolder有以下编译错误:
Error:(5, 22) Result type in structural refinement may not refer to a user-defined value class
def wrapper: Wrapper = w
Run Code Online (Sandbox Code Playgroud)
scala compiler-errors compilation structural-typing value-class
假设我有一个值案例类
case class Id(i:Int) extends AnyVal
Run Code Online (Sandbox Code Playgroud)
以及包含此值case类的序列
Seq(Id(1), Id(2), Id(3))
Run Code Online (Sandbox Code Playgroud)
是否有一种方法可以将这些值转换Int为不需要迭代序列(例如通过执行Seq(Id(1), Id(2), Id(3)).map(_.i)?
我问的原因是我认为值case case类的优点在于你可以使用在运行时具有本机类型作为表示的值类,因此非常有效.但并非所有使用的库都支持这些类的自动"转换".因此,当它是一个简单的属性时,必须传递本机类型,因为编译器可以优化它.但是当有一个序列时我必须显式地映射它,这意味着在所有值上发生了不必要的迭代,因为它实际上什么也没做,只是在运行时映射到相同的值.有没有办法避免这种情况,并在这种情况下使用编译器的一些优化?
我只是无法重写值类上的 hashCode() 函数。最小的例子(我知道在这个例子中不需要覆盖它......)
@JvmInline
value class Identifier(val value: String){
override fun hashCode(): Int = this.value.hashCode()
}
Run Code Online (Sandbox Code Playgroud)
我收到错误:名称为“hashCode”的成员已保留用于未来版本
编辑:有什么方法可以指定自己的 hashCode() 函数吗?
我反思性地调用一个方法,其参数可能是也可能不是值类的实例.由于值类的目的是避免基础值的装箱,如果参数类型是值类,那么所讨论的方法实际上将期望未装箱的值.为了处理这种情况,我试图从值类中解包基础值.我首先需要确定参数是否是值类,在这里我遇到了第一个绊脚石:
def isObjectOfValueClass(arg: Any) =
classOf[AnyVal].isAssignableFrom(arg.getClass)
Run Code Online (Sandbox Code Playgroud)
这不能按预期工作,因为该方法返回true:
case class NonValueClass(underlying: Int)
Run Code Online (Sandbox Code Playgroud)
如何isObjectOfValueClass实施?或者是否有一种更简单的方法来反射调用可能将值类的对象作为参数的方法?
比如说,我定义了一个值类,如下所示
package object p {
class ValueClass[T](val o: Option[T]) extends AnyVal {
def foo: Option[T] =
o collect {
case t => t
}
}
}
Run Code Online (Sandbox Code Playgroud)
编译失败并显示以下消息:
overriding method applyOrElse in trait PartialFunction of type [A1 <: T, B1 >: T](x: A1, default: A1 => B1)B1;
method applyOrElse has incompatible type
o collect {
^
Run Code Online (Sandbox Code Playgroud)
错误消息对我来说似乎没那么有意义,就好像我替换collect了map(需要函数而不是部分函数)或类没有扩展AnyVal,代码片段将编译.
有谁可以解释背后的原因或链接到提交的问题?
我正在使用JavaConverters从Java SortedSet转到Vector.
val lines = function.getInstructions.asScala.toVector
Run Code Online (Sandbox Code Playgroud)
我的getInstructions函数返回java.lang.Long的ArrayList,但消耗代码需要Scala.Long.有没有办法在不改变所有消耗代码的情况下使用Java.lang.Long?
此外,有没有办法隐式转换到值类,以允许随机访问ArrayList而不分配如上所述的额外对象?非常感谢您提供的任何见解.
根据价值类的文件,它们可能在许多情况下分配:
分配摘要
值类被视为另一种类型.
值类被分配给数组.
进行运行时类型测试,例如模式匹配.
无论如何说,如果出现这些情况,会抛出编译错误吗?
这是简化的代码:
class Value(val value: Int) extends AnyVal
val v = new Value(1)
val x = new { val f: Int = v.value }
println(x.f)
val y = new { val f: Value = v }
println(y.f)
Run Code Online (Sandbox Code Playgroud)
错误:结构细化中的结果类型可能不引用用户定义的值类
val y = new { val f: 值 = v }
我不明白。既然Int也是一个值类,为什么Int可以用作成员,而我的值类Value却不能?为什么scala定义了这个限制?如何在结构类型中使用用户定义的值vlass?
我们有两个项目,kotlin 项目发布了一个由 java 导入的包。
在 kotlin 中,是一个像这样的值类
@JvmInline
value class CountryId(private val id: UUID) {
override fun toString(): String = id.toString()
companion object { fun empty(): CountryId = CountryId(EMPTY_UUID) }
}
Run Code Online (Sandbox Code Playgroud)
在java中,我们看不到构造函数,也看不到实际实例化这个类。我还尝试在 Kotlin 中创建一个工厂来创建它们
class IdentifierFactory
{
companion object {
fun buildString(): String {
return "hello"
}
fun buildCountry(): CountryId {
return CountryId.empty()
}
}
}
Run Code Online (Sandbox Code Playgroud)
在java中,我可以调用IdentifierFactory.Companion.buildString()它并且它会工作,但它IdentifierFactory.Companion.buildCountry()甚至不存在。
Java 的 Value 类真的这么糟糕吗?
附:我也尝试过@JvmStatic,但没有成功
pps。如果我从java端反编译kotlin字节码,并得到一个CountryId.decompiled.java,这就是构造函数的样子
// $FF: synthetic method
private CountryId(UUID id) {
Intrinsics.checkNotNullParameter(id, "id");
super();
this.id = …Run Code Online (Sandbox Code Playgroud) 值类可用于实现类型安全,而无需拆箱开销。
我的印象是,在运行时这样的类型/类将“不存在”,被视为简单类型(例如,值类在运行时case class X(i: Int) extends AnyVal将是简单的Int)。
但是,如果您确实.toString在值类实例上调用了一个方法,它将打印如下内容:
scala> val myValueClass = X(3)
myValueClass: X = 3
scala> myValueClass.toString
res5: String = X(3)
Run Code Online (Sandbox Code Playgroud)
所以我猜编译器毕竟包含一些信息?
正如http://docs.scala-lang.org/overviews/core/value-classes.html所承诺的那样,这有效:
class Wrapper(val self: Int) extends AnyVal {
def toHexString: String = java.lang.Integer.toHexString(self)
}
println(12.toHexString)
Run Code Online (Sandbox Code Playgroud)
但这不编译:
class Wrapper(val self: Int) extends AnyVal {
def whyNot: String = java.lang.Integer.toHexString(self)
}
println(12.whyNot)
Run Code Online (Sandbox Code Playgroud)
为什么不?我唯一改变的是方法的名称!
这是错误消息:
error: value whyNot is not a member of Int
println(12.whyNot)
^
Run Code Online (Sandbox Code Playgroud)
是的,我已经仔细检查了里面的schtupit Unicode字符whyNot.
value-class ×11
scala ×9
java ×2
kotlin ×2
compilation ×1
hashcode ×1
reflection ×1
scala-2.10 ×1
seq ×1