Scala - Traços
Uma característica encapsula definições de método e campo, que podem ser reutilizadas misturando-as em classes. Ao contrário da herança de classe, na qual cada classe deve herdar de apenas uma superclasse, uma classe pode misturar qualquer número de características.
Traits são usados para definir tipos de objetos especificando a assinatura dos métodos suportados. Scala também permite que as características sejam parcialmente implementadas, mas as características podem não ter parâmetros de construtor.
Uma definição de característica se parece com uma definição de classe, exceto que usa a palavra-chave trait. A seguir está o exemplo básico de sintaxe de trait.
Sintaxe
trait Equal {
def isEqual(x: Any): Boolean
def isNotEqual(x: Any): Boolean = !isEqual(x)
}
Esta característica consiste em dois métodos isEqual e isNotEqual. Aqui, não fornecemos nenhuma implementação para isEqual onde outro método tem sua implementação. As classes filhas que estendem uma característica podem fornecer implementação para os métodos não implementados. Portanto, um traço é muito semelhante ao que temosabstract classes em Java.
Vamos supor um exemplo de traço Equal contém dois métodos isEqual() e isNotEqual(). O traçoEqual contém um método implementado que é isEqual() então, quando a classe definida pelo usuário Point estende o traço Equal, implementação para isEqual() método em Point classe deve ser fornecida.
Aqui é necessário conhecer dois métodos importantes de Scala, que são usados no exemplo a seguir.
obj.isInstanceOf [Point] Para verificar o tipo de obj e o ponto são iguais, não.
obj.asInstanceOf [Point] significa moldagem exata, pegando o tipo de objeto de objeto e retorna o mesmo tipo de objeto de ponto.
Experimente o programa de exemplo a seguir para implementar características.
Exemplo
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))
}
}
Salve o programa acima em Demo.scala. Os seguintes comandos são usados para compilar e executar este programa.
Comando
\>scalac Demo.scala
\>scala Demo
Resultado
true
false
true
Classes de valor e traços universais
As classes de valor são um novo mecanismo no Scala para evitar a alocação de objetos de tempo de execução. Ele contém um construtor primário com exatamente umvalparâmetro. Ele contém apenas métodos (def) não permitidos, var, val, classes aninhadas, características ou objetos. A classe de valor não pode ser estendida por outra classe. Isso pode ser possível estendendo sua classe de valor com AnyVal. A segurança de tipos de tipos de dados personalizados sem a sobrecarga do tempo de execução.
Vamos dar exemplos de classes de valor Peso, Altura, Email, Idade, etc. Para todos esses exemplos, não é necessário alocar memória no aplicativo.
Uma classe de valor não tem permissão para estender características. Para permitir que as classes de valor estendam as características,universal traits são introduzidos que se estendem por Any.
Exemplo
trait Printable extends Any {
def print(): Unit = println(this)
}
class Wrapper(val underlying: Int) extends AnyVal with Printable
object Demo {
def main(args: Array[String]) {
val w = new Wrapper(3)
w.print() // actually requires instantiating a Wrapper instance
}
}
Salve o programa acima em Demo.scala. Os seguintes comandos são usados para compilar e executar este programa.
Comando
\>scalac Demo.scala
\>scala Demo
Resultado
Ele fornecerá o código hash da classe Wrapper.
Wrapper@13
Quando usar características?
Não existe uma regra firme, mas aqui estão algumas diretrizes a serem consideradas -
Se o comportamento não for reutilizado, torne-o uma classe concreta. Afinal, não é um comportamento reutilizável.
Se puder ser reutilizado em várias classes não relacionadas, torne-o uma característica. Apenas características podem ser misturadas em diferentes partes da hierarquia de classes.
Se você quiser inherit a partir dele no código Java, use uma classe abstrata.
Se você planeja distribuí-lo em forma compilada e espera que grupos externos escrevam classes herdadas dele, você pode se inclinar a usar uma classe abstrata.
Se a eficiência é muito importante, tente usar uma classe.