我已经使用Kotlin的typealias定义了E164电话号码类型:

typealias E164 = String

这使我在代码中传递电话号码时的意图更加清晰,而不仅仅是传递字符串。我认识到并没有使用正确类型的实际强制要求,但这对我来说很好。

现在,我想将E164存储在Android Room数据库中。这可以在没有typealias的情况下工作,但是在typealias中需要TypeConverters。我尝试了这个:
@Entity data class MyModel(@PrimaryKey val e164: E164, val someOtherThing: String)

class E164Converters {
    @TypeConverter
    fun toE164(value: String): E164 = value

    @TypeConverter
    fun toString(e164: E164): String = e164
}

编译器不喜欢E164Converters类的自动生成的Java,因为toString和toE164方法都定义了String-> String的相同转换。
error: Multiple methods define the same conversion. Conflicts with these: CustomTypeConverter(type=E164Converters, method=toString(java.lang.String), from=java.lang.String, to=java.lang.String) public final java.lang.String toE164(@org.jetbrains.annotations.NotNull()

但是,如果我没有定义TypeConverters,则编译器将不知道如何将E164放入数据库中:
error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.
private final error.NonExistentClass e164 = null;

有人知道如何实现吗?

最佳答案

您不需要E164Converters。您可以将E164用作String。喜欢

val a: E164 = "blabla"

fun f(x: String) = x
f(a) // compiles

我猜你在写类似
fun processPhoneNumber(a: E164) {
  // blabla
}

您可以像processPhoneNumber("110")这样调用上面的函数,它可以正常工作。

您说在使用它时会出错
@Entity data class MyModel(
  @PrimaryKey val e164: E164,
  val someOtherThing: String
)

如果您是我,我会考虑将上面的代码替换为:
data class MyModel private constructor(
  @PrimaryKey val e164: String,
  val someOtherThing: String
) {
  companion object {
    operator fun invoke(e164: E164, someOtherThing: String) =
      MyModel(e164, someOtherThing)
  }
}

09-05 13:25