Eu tenho dois classes
que são DTO's
class FooDto (
val a: String,
val b: Double,
)
class BarDto (
val c: String,
val d: String,
)
Agora, quero definir um terceiro AnotherDto
onde defino o tipo de propriedade como BartDto
ou FooDto
.
class AnotherDto (
val e: FooDto || BarDto
)
Obviamente isso não funciona. Eu li sobre sealed classes
, que ficaria assim
sealed class Menu{
data class PIZZA(val name: String, val size:String, val quantity:Int):Menu()
data class BURGER(val quantity:Int, val size:String): Menu()
data class CHICKEN(val quantity:Int, val pieces:String):Menu()
}
No entanto, isso exige que eu defina todas as variáveis (como name: String
e quanitity: Int
) novamente. Não é isso que eu quero, quero simplesmente reaproveitar o que foi definido anteriormente FooDto
e BarDto
sem duplicar.
Então, é isso
sealed class FooBar{
data class Foo(val a: String, val b: Double):FooBar()
data class Bar(val c: String, val d: String): FooBar()
}
é meio inútil porque eu FooDto
já BarDto
escrevi e eles são usados em outro lugar. Eu quero algo assim
sealed class FooBar{
FooDto:FooBar()
BarDto: FooBar()
}
O que obviamente não funciona.
Como reutilizo meus DTO
s já escritos FooDto
e BarDto
faço um "tipo de união" que posso atribuir como tipo de dados a uma variável em Kotlin?
Não acho que você deva rejeitar a herança regular aqui. Além disso, uma interface comum pode ser mais apropriada do que uma classe selada.
Se você quer isso:
Então
FooDto
eBarDto
deve implementar algum tipo de funcionalidade comum para que a propriedadee
seja útil.Então, qualquer que seja a funcionalidade comum, escreva-a em uma interface 1 :
Então você pode implementar a interface em
FooDto
eBarDto
2 e ter:Isso ainda não parece concluído porque provavelmente você deseja
AnotherDto
se parecer com umDto
objeto normal. Então você pode usar o recurso de delegação eAnotherDto
ficará no lugar de qualquer outroDto
que for passado para seu construtor:1 Classes seladas/abstratas também são possíveis, mas uma interface é mais flexível quando a implementação de classes é menos acoplada
2 Sim, envolve mudança dessas classes; mas um tipo de união não seria útil sem pelo menos uma interface compartilhada (a menos que você vá empregar reflexão ou similar, o que certamente deve ser o último recurso)
Você poderia usar uma
Either
classe. Você pode usar um pré-existente de uma biblioteca como Arrow ( https://apidocs.arrow-kt.io/arrow-core/arrow.core/-either/index.html ) ou implementar um você mesmo assim:No call-site, agora você pode fazer o seguinte: