Qual é a vantagem de usar uma classe abstrata em vez de uma característica (além do desempenho)? Parece que as classes abstratas podem ser substituídas por características na maioria dos casos.
371
Eu posso pensar em duas diferenças
Há uma seção em Programação em Scala chamada "Caracterizar ou não caracterizar?" que aborda esta questão. Como a 1ª edição está disponível on-line, espero que seja correto citar tudo aqui. (Qualquer programador Scala sério deve comprar o livro):
Como o @Mushtaq Ahmed mencionou, uma característica não pode ter nenhum parâmetro passado para o construtor primário de uma classe.
Outra diferença é o tratamento de
super
.Veja o restante do capítulo 12 para mais detalhes.
Edição 1 (2013):
Há uma diferença sutil na maneira como as classes abstratas se comportam em comparação com as características. Uma das regras de linearização é que ela preserva a hierarquia de herança das classes, que tende a empurrar classes abstratas mais tarde na cadeia, enquanto os traços podem ser misturados com alegria. Em certas circunstâncias, é realmente preferível estar na última posição da linearização de classes , então classes abstratas podem ser usadas para isso. Consulte Linearização de classe restritiva (ordem de mixagem) em Scala .
Edição 2 (2018):
No Scala 2.12, o comportamento de compatibilidade binária do traço mudou. Antes da versão 2.12, adicionar ou remover um membro à característica exigia a recompilação de todas as classes que herdam a característica, mesmo que as classes não tenham sido alteradas. Isso se deve à maneira como as características foram codificadas na JVM.
No Scala 2.12, os traços são compilados nas interfaces Java , portanto, o requisito diminuiu um pouco. Se a característica seguir um destes procedimentos, suas subclasses ainda exigirão recompilação:
Mas se a característica não existir, você poderá atualizá-la sem interromper a compatibilidade binária.
fonte
If outside clients will only call into the behavior, instead of inheriting from it, then using a trait is fine
- Alguém poderia explicar qual é a diferença aqui?extends
vswith
?extends
ewith
. É puramente sintático. Se você herdar de vários modelos, o primeiro recebeextend
, todos os outros recebemwith
, é isso. Pensewith
como uma vírgula:class Foo extends Bar, Baz, Qux
.Por tudo o que vale a pena, a Programação em Scala de Odersky et al recomenda que, quando você duvida, use traços. Você sempre pode transformá-los em classes abstratas posteriormente, se necessário.
fonte
Além do fato de que você não pode estender diretamente várias classes abstratas, mas você pode misturar várias características em uma classe, vale mencionar que as características são empilháveis, pois as super chamadas em uma característica são dinamicamente ligadas (está se referindo a uma classe ou característica misturada antes atual).
Da resposta de Thomas na diferença entre classe abstrata e característica :
fonte
Ao estender uma classe abstrata, isso mostra que a subclasse é de um tipo semelhante. Este não é necessariamente o caso ao usar traços, eu acho.
fonte
Na Programming Scala, os autores dizem que as classes abstratas fazem um relacionamento clássico "is-a" orientado a objetos, enquanto os traços são um modo de composição de scala.
fonte
As classes abstratas podem conter comportamento - elas podem ser parametrizadas com argumentos do construtor (que não podem ser características) e representam uma entidade que funciona. Os traços representam apenas um único recurso, uma interface de uma funcionalidade.
fonte
trait Enumerable
com muitas funções auxiliares, eu não as chamaria de comportamento, mas apenas de funcionalidade conectada a um recurso.fonte