首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >scala 3不透明类型:无法调用在扩展中定义的方法

scala 3不透明类型:无法调用在扩展中定义的方法
EN

Stack Overflow用户
提问于 2022-08-25 21:29:26
回答 1查看 72关注 0票数 0

我的代码大部分是从Scala 3书借来的

代码语言:javascript
复制
object Logarithms:
//vvvvvv this is the important difference!
  opaque type Logarithm = Double

  object Logarithm:
    def apply(d: Double): Logarithm = math.log(d)

  extension (x: Logarithm)
    def toDouble: Double = math.exp(x)
    def + (y: Logarithm): Logarithm = x + math.log1p(math.exp(y-x))
    def * (y: Logarithm): Logarithm = x + y
    //  vvvvvvvvv these two do not work!
    def toString: String = x.asInstanceOf[Logarithm].toDouble.toString
    def toString2: String = x.asInstanceOf[Logarithm].toDouble.toString
    //def toString: String = x.toDouble.toString // does not work either

问题是我无法使toString工作,它不能从内部表示转换值:

代码语言:javascript
复制
$ ~/Downloads/scala3-3.1.3/bin/scala
Welcome to Scala 3.1.3 (14.0.1, Java OpenJDK 64-Bit Server VM).

scala> import Logarithms.*
                                                                                                                           
scala> Logarithm(4)
val res0: Logarithms.Logarithm = 1.3862943611198906   <<== the internal representation
                                                                                                                           
scala> Logarithm(4).toDouble
val res1: Double = 4.0                                <<== as expected
                                                                                                                           
scala> Logarithm(4).toDouble.toString
val res2: String = 4.0                                <<== as expected
                                                                                                                           
scala> Logarithm(4).toString
val res3: String = 1.3862943611198906                 <<== expected: 4.0 !!!
                                                                                                                           
scala> Logarithm(4).toString2
val res4: String = 1.3862943611198906                 <<== expected: 4.0 !!!

如何在不复制toDouble 中的代码的情况下定义toString

UPD

代码语言:javascript
复制
def toString: String = "log:"+x.asInstanceOf[Logarithm].toDouble.toString
def toString2: String = "log:"+x.asInstanceOf[Logarithm].toDouble.toString

我得到了

代码语言:javascript
复制
scala> Logarithm(4).toString
val res0: String = 1.3862943611198906               <<== expected: log:4.0
                                                                                                                           
scala> Logarithm(4).toString2
val res1: String = log:1.3862943611198906           <<== expected: log:4.0
EN

回答 1

Stack Overflow用户

发布于 2022-08-26 14:06:13

关于你问题的那一部分

如何在不复制toString代码的情况下定义toDouble

只是不要叫它"toDouble“。在已知不透明类型为Double的上下文中,toDouble方法将被解释为只是通常的Double#toDouble (即它什么也不做)。如果您将toDouble重命名为类似于toLinear的东西(在toString2内部使用),那么toLinear将不会与内置的toDouble发生冲突,您的toString2将按预期工作:

代码语言:javascript
复制
opaque type Logarithm = Double

object Logarithm:
  def apply(d: Double): Logarithm = math.log(d)

extension (x: Logarithm)
  private def toLinear: Double = math.exp(x)
  def toDouble: Double = toLinear
  def toString2: String = s"Logarithm(${x.toLinear.toString})"

println(Logarithm(4.0).toString2) // Logarithm(4.0)

但是,您不能对toString做任何事情,因为toString是在AnyRef / java.lang.Object上定义的,而您只是无法摆脱它。您可以尝试使用Show类型,这取决于它是否适合您的项目。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73493887

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档