【问题标题】:using apply methods in a Trait in Scala在 Scala 的 Trait 中使用 apply 方法
【发布时间】:2013-10-30 12:08:45
【问题描述】:

根据我在 X 中传递的对象类型,我需要使用 apply 方法。我可以指定要使用的修饰符(Y 或 Z)。我需要使用这样的“跟随”函数的语法:

(object of type B) following Y

(object of type C) following Z

代码如下:

trait A 
{
    def following(modifier: X) = modifier(this)
}
case class B() extends A{}
case class C() extends A{}
trait X {}
object Y extends X
{
    apply(obj: B):B = {}
    apply(obj: C):C = {}
}
object Z extends X
{
    apply(obj: B):B = {}
    apply(obj: C):C = {}
}

编译器在我实现“以下”功能的行中给出错误。我做错了什么?

【问题讨论】:

  • 你期望这个函数的结果是什么,你得到了什么错误?
  • 例如:我需要更改 B 类对象的一个​​字段。因此,修饰符 Y 采用 B 类型的对象,更改其中一个字段(我已跳过其逻辑)并返回一个相同类型的对象,但其中一个字段已更改。
  • 我建议将该信息添加到问题中(例如,显示预期用途和结果)以及您遇到的实际错误。

标签: scala apply traits


【解决方案1】:

我猜你想要的是这样的:

    trait X {
        def apply[T](obj: T): T
    }

    trait A {
        def following(modifier: X) = modifier(this)
    }

    case class B() extends A
    case class C() extends A

    object Y extends X {
        override def apply[B](obj: B): B = { obj }
        override def apply[C](obj: C): C = { obj }
    }

    object Z extends X {
        override def apply[B](obj: B): B = { obj }
        override def apply[C](obj: C): C = { obj }
    }

不幸的是,我认为您不能有两个覆盖的 apply 方法,因此它不会编译。如果这是可能的,那么我也很乐意知道。你现在可以做的是使用一种应用模式匹配的方法:

    trait X {
        def apply[T](obj: T): T
    }

    trait A {
        def following(modifier: X) = modifier(this)
    }

    case class B() extends A
    case class C() extends A

    object Y extends X {
        override def apply[T](obj: T): T = {
            obj match {
                case o: B => obj
                case o: C => obj
            }
        }
    }

    object Z extends X {
        override def apply[T](obj: T): T = {
            obj match {
                case o: B => obj
                case o: C => obj
            }
        }
    }

您也可以通过其他方式获得完全相同的效果(包括语法)。 在我看来更简洁,更容易理解:

    sealed trait X
    case class Y() extends X
    case class Z() extends X

    trait A[T] {
        def following(modifier: X): T
    }

    case class B() extends A[B] {
        override def following(modifier: X) = modifier match {
            case o: Y => this
            case o: Z => this
        }
    }

    case class C() extends A[C] {
        override def following(modifier: X) = modifier match {
            case o: Y => this
            case o: Z => this
        }
    }

【讨论】:

    【解决方案2】:

    你做错了几件事:

    1. 您在 Y 和 Z 中的 apply 定义必须是 def
    2. 特征 X 需要定义 apply 方法,但只能作为抽象方法。
    3. following 需要在 B 和 C 中重写,以便编译器知道要调用 X 中的哪个重载方法。
    4. following 需要在 A 中抽象。

    您正在实施访问者模式。我建议找一份the gang of four book 的副本,并根据其中的示例进行操作。

    【讨论】:

      猜你喜欢
      • 2023-03-29
      • 2013-11-26
      • 1970-01-01
      • 1970-01-01
      • 2012-08-04
      • 1970-01-01
      • 2015-04-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多