当我没有实例时,我想要一些带有伴随对象的类,以便从类实例和伴随对象访问共享值。
最终我想解析一个字符串并创建匹配类的实例,反之亦然,从一个实例创建一个字符串。
以下代码有效,但似乎过于复杂:
abstract class Person(val age: Int = 0) {
val pronoun: String
override def toString = pronoun + " is " + age + " years old"
}
class Man(override val age: Int) extends Person {
val pronoun = Man.pronoun
}
class Woman(override val age: Int) extends Person {
val pronoun = Woman.pronoun
}
object Man extends Person {
val pronoun = "he"
}
object Woman extends Person {
val pronoun = "she"
}
object Person {
def fromString(pronoun: String, age: Int): Option[Person] = {
pronoun match {
case Man.pronoun => Some(new Man(age))
case Woman.pronoun => Some(new Woman(age))
case _ => None
}
}
}
// Man.pronoun
// -> should return "he"
// Woman.pronoun
// -> should return "she"
// new Man(30).toString
// -> should return "he is 30 years old"
// Person.fromString("she", 20)
// -> should return a Some(Woman) with age = 20
因此,为此,我为每个子类创建一个类和一个伴随对象,并从伴随对象手动引用pronoun
(例如val pronoun = Man.pronoun
)。
旁注:在抽象类中设置默认值age = 0
会使事情变得更容易一些,但看起来不对吗?!
我尝试过使用特征等但都没有成功。有没有更好的方法来实现这一点,重复性较低的代码?
答案 0 :(得分:1)
您必须遵循哪些限制条件?例如。你必须能够调用Man.pronoun
吗?因为一个选项是简单地在ManPronoun
对象中创建WomanPronoun
和Person
字段,然后移除Man
和Woman
个随播广告对象。另外,0默认年龄值的重点是什么?您只需将年龄传递给Person
。
abstract class Person(val age: Int) {
val pronoun: String
override def toString = pronoun + " is " + age + " years old"
}
class Man(override val age: Int) extends Person(age) {
val pronoun = Person.ManPronoun
}
class Woman(override val age: Int) extends Person(age) {
val pronoun = Person.WomanPronoun
}
object Person {
val ManPronoun = "he"
val WomanPronoun = "she"
def fromString(pronoun: String, age: Int): Option[Person] = {
pronoun match {
case ManPronoun => Some(new Man(age))
case WomanPronoun => Some(new Woman(age))
case _ => None
}
}
}
如果您必须在Man
和Woman
对象中包含代词字段,那么您必须拥有Man
和Woman
个对象。 :)
答案 1 :(得分:1)
考虑到这个问题,我会通过以下方式简化它:
case class Person(pronoun: String, age: Int) {
override def toString = s"$pronoun is $age years old"
}
这应该解决它,但我想你提出的问题是一个更复杂的问题的简化,所以我的解决方案变成了:
trait Person {
protected def age: Int
protected def pronoun: String
override def toString = s"$pronoun is $age years old"
}
case class Man(override val age: Int) extends Person {
override protected def pronoun: String = Person.SHE
}
case class Woman(override val age: Int) extends Person {
override protected def pronoun: String = Person.HE
}
object Person {
val HE = "he"
val SHE = "she"
def parse(pronoun: String, age: Int): Option[Person] = {
pronoun match {
case HE => Some(Man(age))
case SHE => Some(Woman(age))
case _ => throw new IllegalArgumentException(s"pronoun $pronoun was not recognized")
}
}
}
这对我来说看起来不太好,解决问题并且非常易读。 话虽如此,你的代码看起来并不错(0默认值)。这看起来很复杂,但我花了2秒钟来了解你在做什么,而且可读性在这些日子里非常重要。
希望这会对你有所帮助。此致!