Qual é a lógica por trás de ter objetos companheiros no Scala?


Respostas:


82

O objeto companheiro basicamente fornece um local onde se pode colocar métodos "do tipo estático". Além disso, um objeto companheiro, ou módulo companheiro, tem acesso total aos membros da classe, incluindo os particulares.

Os objetos companheiros são ótimos para encapsular coisas como métodos de fábrica. Em vez de ter que ter, por exemplo, Fooe em FooFactorytodos os lugares, você pode fazer com que uma classe com um objeto companheiro assuma as responsabilidades da fábrica.


61

Os objetos complementares são úteis para armazenar estados e métodos comuns a todas as instâncias de uma classe, mas não usam métodos ou campos estáticos . Eles usam métodos virtuais regulares que podem ser substituídos por herança. Scala realmente não tem nada estático. Existem muitas maneiras de usar isso, mas aqui está um exemplo simples.

abstract class AnimalCounter
{
    var animals = 0

    def name: String

    def count()
    {
        animals += 1
        println("%d %ss created so far".format(animals, name))
    }
}

abstract class Animal
{
    def companion: AnimalCounter
    companion.count()
}

object Dog extends AnimalCounter
{
    val name = "dog"
}

class Dog extends Animal
{
    def companion = Dog
}

object Cat extends AnimalCounter
{
    val name = "cat"
}

class Cat extends Animal
{
    def companion = Cat
}

O que produz esta saída:

scala> new Dog
1 dogs created so far

scala> new Cat
1 cats created so far

scala> new Dog
2 dogs created so far

scala> new Cat
2 cats created so far

1
ilustração semelhante pode ser encontrada também aqui: daily-scala.blogspot.sk/2009/09/companion-object.html
xhudik

30

... e é um bom lugar para armazenar métodos de fábrica estáticos (não aquele DP) para classes acompanhadas. Se você nomear esses métodos de fábrica sobrecarregados como (/ ... /), você será capaz de criar / inicializar sua classe

  1. sem 'novo' (não é tão importante)

  2. com diferentes conjuntos de parâmetros possíveis (compare com o que Bloch escreve em Effective Java sobre construtor telescópico)

  3. com a capacidade de decidir qual classe derivada você deseja criar em vez da abstrata (acompanhada)

Código de exemplo:

abstract class AbstractClass;
class RealThing(s: String) extends AbstractClass;
class AlternativeThing(i: Int) extends AbstractClass;
object AbstractClass {
  def apply(s: String) = {
    new RealThing(s)
  }
  def apply(i: Int) = {
    new AlternativeThing(i)
  }
}

// somewhere else you can
val vs = AbstractClass("asdf")  // gives you the RealThing wrapped over string
val vi = AbstractClass(123)  // gives you AlternativeThing wrapped over int

Eu não chamaria o objeto / classe base de AbstractXxxxx porque não parece ruim: como criar algo abstrato. Dê a esses nomes um significado real. Considere o uso de classes de caso imutáveis, sem método, e sele a classe base abstrata.


2
RealThinge a AlternativeThingclasse deve ter um privateconstrutor para forçar o usuário a usar a AbstractClassfábrica. class AlternativeThing private(i: Int) extends AbstractClass
reunião de

@ [Szymon Jachim] A classe abstrata Scala não suporta herança múltipla. Então, por que o compilador permite isso no seu caso?
user2441441

19

Além das coisas que Saem disse em sua resposta , o compilador Scala também procura conversões implícitas de tipos nos objetos complementares correspondentes (da origem ou do destino), portanto, as conversões não precisam ser importadas.

Sobre a razão para objetos singleton em geral, a programação em Scala diz:

Conforme mencionado no Capítulo 1, uma maneira pela qual Scala é mais orientado a objetos do que Java é que as classes em Scala não podem ter membros estáticos. Em vez disso, Scala possui objetos singleton (p. 65).


3

Sempre vejo os objetos complementares como uma ponte para escrever código funcional e orientado a objetos em Scala. Muitas vezes, precisamos apenas de funções puras que recebem alguma entrada e fornecem um resultado de processamento. Colocar essas funções relevantes no objeto complementar facilita a pesquisa e o uso, tanto para mim quanto para quem está construindo sobre meu código.

Além disso, é um recurso fornecido pela linguagem para escrever o padrão singleton sem fazer nada. Isso é especialmente útil quando você precisa de um singleton para encapsular um delegador para a vida da JVM. Por exemplo, escrever uma biblioteca cliente HTTP simples em Scala onde você pode encapsular um delegador baseado em implementação Java subjacente e permitir que os consumidores de sua API vivam em um mundo puro.


0

Se você definir classe e objeto no mesmo arquivo com o mesmo nome, eles são conhecidos como classe e objeto complementares. Scala não tem static como palavra-chave JAVA, você pode tomar como substituição de static com classe companion e objeto em Scala.

Para obter informações mais detalhadas, verifique a classe do artigo e a palavra-chave do objeto em programação scala


-1

A princípio, ele fornece uma separação clara dos métodos de métodos estáticos e não estáticos. Também fornece uma maneira simples de criar uma classe de singleton.

Ele também pode herdar métodos de outras classes e / ou características, o que não pode ser feito com métodos estáticos Java e pode ser passado como um parâmetro.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.