问题
I have a Kotlin data class:
data class PaymentAccount(
val accountId: Int,
val accountNumber: String,
val title: String
)
This is what I'd do in Java:
Create an abstract class:
public abstract class PaymentAccount {
protected int accountId;
protected String accountNumber;
protected String title;
public PaymentAccount(int accountId,
String accountNumber,
String title) {
this.accountId = accountId;
this.accountNumber = accountNumber;
this.title = title;
}
}
Create null object and extend abstract class:
public class NullPaymentAccount extends PaymentAccount {
public NullPaymentAccount() {
super(-1,
"Invalid account number",
"Invalid title");
}
}
Create a real object and extend abstract class too:
public class RealPaymentAccount extends PaymentAccount {
public RealPaymentAccount(int accountId,
String accountNumber,
String title) {
super(accountId,
accountNumber,
title);
}
}
How to implement Null Object pattern in Kotlin properly? Is there more than one way? If so, what is the most concise and elegant way?
回答1:
In Kotlin you can do the same, just with less lines of code:
interface Account {
val accountId: Int
val accountNumber: String
val title: String
}
object EmptyAccount : Account {
override val accountId: Int = 1
override val accountNumber: String = ""
override val title: String = ""
}
data class PaymentAccount(
override val accountId: Int,
override val accountNumber: String,
override val title: String): Account
Notice that we also make EmptyAccount
singletone for efficiency.
回答2:
While the solution you've been given already is fine, you might not need to have an explicit class to represent a null state if your default values aren't all or nothing. I would argue that providing defaults for all of your fields is the null object pattern.
For example, you could write your class like this:
data class PaymentAccount(
val accountId: Int = -1,
val accountNumber: String = "Invalid Account Number",
val title: String = "Invalid Title"
)
And when you construct them:
PaymentAccount(1, "Acct2", "Checking") // Actual data
PaymentAccount() // Default values, therefore a "null" object.
The only real problem is when you only specify some of the values, but that might be ok/desirable:
PaymentAccount(1) // accountNumber and title have defaults
来源:https://stackoverflow.com/questions/51847914/how-to-implement-null-object-pattern-on-data-class-in-kotlin