“Nova” palavra-chave em Scala

93

Eu tenho uma pergunta muito simples - quando devemos aplicar a nova palavra-chave ao criar objetos no Scala? É quando tentamos instanciar apenas objetos Java?

Bober02
fonte

Respostas:

144

Use a newpalavra - chave quando quiser se referir ao classpróprio construtor de:

class Foo { }

val f = new Foo

Omita newse você estiver se referindo ao applymétodo do objeto complementar :

class Foo { }
object Foo {
    def apply() = new Foo
}

// Both of these are legal
val f = Foo()
val f2 = new Foo

Se você fez uma aula de caso:

case class Foo()

Scala secretamente cria um objeto companheiro para você, transformando-o neste:

class Foo { }
object Foo {
    def apply() = new Foo
}

Então você pode fazer

f = Foo()

Por último, lembre-se de que não há regra que diga que o apply método complementar deve ser um proxy para o construtor:

class Foo { }
object Foo {
    def apply() = 7
}

// These do different things
> println(new Foo)
test@5c79cc94
> println(Foo())
7

E, já que você mencionou as classes Java: sim - as classes Java raramente têm objetos companheiros com um applymétodo, então você deve usar newe o construtor da classe real.

Owen
fonte
1
Uma classe Java nunca pode ter um objeto complementar. Ele pode ter um objeto que pode funcionar como um Factory para a classe Java - mas esse objeto não é seu objeto companheiro.
kiritsuku
@Antoras Visto que as classes Scala são compiladas para bytecode Java e podem ser distribuídas em forma compilada, Scala pode dizer a diferença entre um companheiro Scala real e uma classe chamada Foo $ com um membro MODULE $ estático?
Owen
1
Acho que scalac pode diferir disso porque é especificado que um objeto complementar deve ser declarado no mesmo arquivo que sua classe complementar. Como a "propriedade" complementar existe apenas no Scala e não no scalac em nível de Bytecode, é necessário verificar o código do Scala e não o Bytecode para ter certeza de que a especificação é seguida.
Kiritsuku de
1
Algum exemplo de classes Java que NÃO usam nova palavra-chave em Scala?
Bober02
Além disso, os métodos no objeto companheiro serão disponibilizados por meio de métodos estáticos na classe e isso nunca acontecerá com classes java para as quais você definirá um "companheiro" posteriormente.
drexin
16

É quando tentamos instanciar apenas objetos java?

De modo nenhum. Há dois casos gerais em que você omite newna escala. Com objetos singleton (que geralmente são usados ​​para armazenar funções estáticas e como uma espécie de fábrica semelhante ao que você pode ver em java):

scala> object LonelyGuy { def mood = "sad" }
defined module LonelyGuy

scala> LonelyGuy
res0: LonelyGuy.type = LonelyGuy$@3449a8

scala> LonelyGuy.mood
res4: java.lang.String = sad

Com classes de caso (na verdade, embaixo há classe + objeto = padrão companheiro , por exemplo, tendo classe e objeto com o mesmo nome):

scala> case class Foo(bar: String) 
defined class Foo


scala> Foo("baz")
res2: Foo = Foo(baz)

Portanto, quando você trabalha com classes simples, as regras são as mesmas do Java.

scala> class Foo(val bar: String) 
defined class Foo

scala> new Foo("baz")
res0: Foo = Foo@2ad6a0

// will be a error 
scala> Foo("baz")
<console>:8: error: not found: value Foo
       Foo("baz")

Bônus, existe uma classe anônima em scala, que pode ser construída assim:

scala> new { val bar = "baz" }
res2: java.lang.Object{val bar: java.lang.String} = $anon$1@10ee5b8

scala> res2.bar
res3: java.lang.String = baz
om-nom-nom
fonte
1
Você está bem, amigo?
Jacob B
0

É quando tentamos instanciar apenas objetos Java?

Com Scala 3 (que deve ser lançado em meados de 2020, oito anos depois), baseado em Dotty : nunca.

Scala 3 irá eliminar " new", como neste tópico

Os aplicativos criadores permitem usar a sintaxe de chamada de função simples para criar instâncias de uma classe, mesmo se não houver nenhum método de aplicação implementado.

Exemplo:

class StringBuilder(s: String) {
   def this() = this(s)
}

StringBuilder("abc")  // same as new StringBuilder("abc")
StringBuilder()       // same as new StringBuilder()

Os aplicativos criadores generalizam uma funcionalidade fornecida até agora apenas para classes de caso, mas o mecanismo como isso é obtido é um pouco diferente.
Em vez de um método de aplicação gerado automaticamente, adicionamos uma nova interpretação possível a uma chamada de função f(args).

VonC
fonte