Scala 特征(Trait)

  • 特征

    特征封装了方法和字段定义,然后可以通过将它们混合到类中来重用它们。与类继承(每个类只能从一个超类继承)不同,一个类可以混合任意数量的特征。特性用于通过指定所支持方法的签名来定义对象类型。Scala还允许部分实现特征,但是特征可能没有构造函数参数。特征定义看起来类似于类定义,只是它使用关键字trait。以下是trait的基本示例语法。
    
    trait Equal {
       def isEqual(x: Any): Boolean
       def isNotEqual(x: Any): Boolean = !isEqual(x)
    }
    
    特征包含两个方法isEqualisNotEqual。在这里,我们没有给出isEqual的任何实现,而另一种方法已经实现了。扩展特性的子类可以为未实现的方法提供实现。因此,特征与Java中的抽象类非常相似。让我们假设一个特性为Equal的示例包含两个方法isEqual()和isNotEqual()。特征Equal包含一个已实现的方法isEqual(),因此当用户定义的类Point扩展特征Equal时,应提供对Point类中isEqual()方法的实现。在这里,需要知道两种重要的Scala方法,在以下示例中将使用它们。
    • obj.isInstanceOf [Point]要检查obj的类型和Point是否相同。
    • obj.asInstanceOf [Point]表示通过采用对象obj类型进行精确转换,并返回与Point类型相同的obj。
    尝试使用以下示例程序来实现特征。
    输出-
    
    trait Equal {
       def isEqual(x: Any): Boolean
       def isNotEqual(x: Any): Boolean = !isEqual(x)
    }
    
    class Point(xc: Int, yc: Int) extends Equal {
       var x: Int = xc
       var y: Int = yc
       
       def isEqual(obj: Any) = obj.isInstanceOf[Point] && obj.asInstanceOf[Point].x == y
    }
    
    object Demo {
       def main(args: Array[String]) = {
          val p1 = new Point(2, 3)
          val p2 = new Point(2, 4)
          val p3 = new Point(3, 3)
    
          println(p1.isNotEqual(p2))
          println(p1.isNotEqual(p3))
          println(p1.isNotEqual(2))
       }
    }
    
    尝试一下
    输出:
    
    Wrapper@3
    
  • 何时使用特征?

    没有严格的规则,但是这里要考虑的准则很少-
    • 如果该行为不会被重用,那么将其作为一个具体类。它毕竟不是可重用的行为。
    • 如果它可以在多个不相关的类中重用,那么将它作为一个trait。只有特征可以混合到类层次结构的不同部分中。
    • 如果您想在Java代码中继承它,请使用一个抽象类。
    • 如果您计划以编译的形式发布它,并且希望外部组编写继承它的类,那么您可能倾向于使用抽象类。
    • 如果效率是非常重要的,倾向于使用类。