如何在 Scala 中多次继承通用特征?

如何解决如何在 Scala 中多次继承通用特征?

我有一个看起来像这样的特征:

trait Ingredient[T] {
  def foo(t: T): Unit = {
    // Some complex logic
  }
}

以及我想要方法的类型:

class Cheese
class Pepperoni
class Oregano

如何制作另一个具有方法的特征:

def foo(t: Cheese)
def foo(t: Pepperoni)
def foo(t: Oregano)

不复制代码?以下将不起作用,因为它多次从同一特征中非法继承:

trait Pizza extends Ingredient[Cheese] with Ingredient[Pepperoni] with Ingredient[Oregano] {}

解决方法

我将提供两种解决方案:

  1. 如果您可以将 CheesePepperoniOregano 定义为特征,您可以这样做:

    trait Ingredient {
       def foo[T <: Ingredient](t: T): Unit = {
         println(t)
       }
     }
    

    然后扩展它:

    trait Cheese extends Ingredient {
      override def toString: String = "Cheese"
    }
    trait Pepperoni extends Ingredient {
      override def toString: String = "Pepperoni"
    }
    trait Oregano extends Ingredient {
      override def toString: String = "Oregano"
    }
    

    用法是:

    trait Pizza extends Ingredient
    
    val pizza = new Pizza { }
    
    pizza.foo(new Cheese { })
    pizza.foo(new Pepperoni { })
    pizza.foo(new Oregano { })
    

    代码在 Scastie 运行。

  2. 使用密封特性。这种方法将成分与问题中绑定的最终产品分开:

    sealed trait Ingredient
    sealed trait PizzaIngredient extends Ingredient
    case object Cheese extends PizzaIngredient
    case object Pepperoni extends PizzaIngredient
    case object Oregano extends PizzaIngredient
    case object Cucumber extends Ingredient
    

    然后定义 Pizza 特征:

    trait Pizza {
        def foo[T <: PizzaIngredient](t: T): Unit = {
          println(t)
        }
    }
    

    用法是:

    val pizza = new Pizza { }
    pizza.foo(Cheese)
    pizza.foo(Pepperoni)
    pizza.foo(Oregano)
    

    代码运行于 Scastie

,

解决方案是创建扩展 Ingredient trait 中的 Pizza trait 的对象。这样我们就有了:

trait Pizza {
  object CheeseIngredient extends Ingredient[Cheese]
  object PepperoniIngredient extends Ingredient[Pepperoni]
  object OreganoIngredient extends Ingredient[Oregano]
}

然后我们可以在继承的对象上调用我们的方法:

object LargePizza extends Pizza {
  def bar(cheese: Cheese,pepperoni: Pepperoni,oregano: Oregano): Unit = {
    CheeseIngredient.foo(cheese)
    PepperoniIngredient.foo(pepperoni)
    OreganoIngredient.foo(oregano)
  }
}

或者,如果我们在 Ingredient trait 中只有几个方法,我们可以创建重载并封装我们的支持对象:

trait Pizza {
  private object CheeseIngredient extends Ingredient[Cheese]
  private object PepperoniIngredient extends Ingredient[Pepperoni]
  private object OreganoIngredient extends Ingredient[Oregano]

  def foo(cheese: Cheese): Unit = CheeseIngredient.foo(cheese)
  def foo(pepperoni: Pepperoni): Unit = PepperoniIngredient.foo(pepperoni)
  def foo(oregano: Oregano): Unit = OreganoIngredient.foo(oregano)
}

object LargePizza extends Pizza {
  def bar(cheese: Cheese,oregano: Oregano): Unit = {
    foo(cheese)
    foo(pepperoni)
    foo(oregano)
  }
}

同样可以通过在 LargePizza 中使用导入来实现。添加重载更好,因为客户端不需要编写额外的导入并且在范围内没有支持对象。使用重载的另一个好处是可以在子类中覆盖方法。

,

如果意图是 Pizza 需要所有这三种成分,那怎么样

class Pizza extends Ingredient[(Cheese,Pepperoni,Oregano)] {

   def foo(ingredients: (Cheese,Oregano)) = {
      case (cheese,pepperoni,oregano) =>
          // do something with them
   }

 }
,

也许您可以执行以下操作,您必须更改 foo 方法:

    trait Ingredient[T] {

   def foo(ingredients: T*): Unit = {
     for (i <- ingredients) {
        // some complex logic
      }
   }
}
    class Cheese 
    class Pepperoni 
    class Oregano 

 
trait Pizza  extends Ingredient[(Cheese,Oregano)]

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?