Scala:从子类动态访问伴随对象
我想要两个带有伴生对象的类,以便在我没有实例时从类实例以及伴生对象访问共享值 最后,我想解析一个字符串并创建匹配类的实例,反过来,从实例创建一个字符串 以下代码可以工作,但似乎过于复杂:Scala:从子类动态访问伴随对象,scala,Scala,我想要两个带有伴生对象的类,以便在我没有实例时从类实例以及伴生对象访问共享值 最后,我想解析一个字符串并创建匹配类的实例,反过来,从实例创建一个字符串 以下代码可以工作,但似乎过于复杂: abstract class Person(val age: Int = 0) { val pronoun: String override def toString = pronoun + " is " + age + " years old" } class Man(override va
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
因此,为了实现这一点,我为每个子类创建了一个类和一个同伴对象,并手动引用同伴对象中的代词
(例如val-degen=Man.degen
)
旁注:在抽象类中设置默认值age=0
,会让事情变得更简单,但这似乎不对
我尝试过使用特质等,但都没有成功。有没有更好的方法可以用更少的重复代码来实现这一点?您必须遵循哪些约束条件?例如,你必须能够调用人代词吗?因为一个选项是简单地在
Person
对象中创建mandeon
和womandeon
字段,并删除Man
和Woman
同伴对象。另外,0默认年龄值有什么意义?您只需将年龄传递给个人
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
对象中包含代词字段: 您必须遵循哪些约束条件?例如,你必须能够调用人代词吗?因为一个选项是简单地在Person
对象中创建mandeon
和womandeon
字段,并删除Man
和Woman
同伴对象。另外,0默认年龄值有什么意义?您只需将年龄传递给个人
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
对象中包含代词字段: 考虑到这个问题,我会通过以下方式简化它:
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秒钟才明白你在做什么,而可读性在这些日子里非常重要
希望这对你有帮助。问候 考虑到这个问题,我会通过以下方式简化它:
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秒钟才明白你在做什么,而可读性在这些日子里非常重要
希望这对你有帮助。问候 没错,我上面的例子是一个简化。我想我的问题是,我没有考虑把“代词”放在宾语中。其次,我不知道我确实可以在这里使用trait而不是抽象类。虽然与第二个答案非常相似,但我会选择这一个作为正确答案,因为我发现这里的特质解决方案稍微干净一些。谢谢没错,我上面的例子是一个简化。我想我的问题是,我没有考虑把“代词”放在宾语中。其次,我不知道我确实可以在这里使用trait而不是抽象类。虽然与第二个答案非常相似,但我会选择这一个作为正确答案,因为我发现这里的特质解决方案稍微干净一些。谢谢也非常感谢您的解决方案!我将默认值设置为0,因为每个扩展了
Person
的类都有相应的对象,这些类需要一个age
参数。我没有选择这个作为“正确”答案的唯一原因是,对于trait解决方案,我不必带着age
参数。这可能会对其他要求很方便,所以也谢谢你的回答。哈,没问题,我不在乎被选为“正确”,而是关心帮助。我把它作为一个抽象类留下,只是因为你是这样做的:)我也更喜欢traits。如果你没有特别的理由使用抽象类,那么就倾向于traits。当你开始把它们堆放在一起时,它们会很有趣。也非常感谢你的解决方案!我将默认值设置为0,因为每个扩展了Person
的类都有相应的对象,这些类需要一个age
参数。我没有选择这个作为“正确”答案的唯一原因是,对于trait解决方案,我不必带着age
参数。这可能会对其他要求很方便,所以也谢谢你的回答。哈,没问题,我不在乎被选为“正确”,而是关心帮助。我把它作为一个抽象类留下,只是因为你是这样做的:)我也更喜欢traits。如果你没有特别的理由使用抽象类,那么就倾向于traits。当你开始把它们堆放在一起时,它们会很有趣。