无法通过配套对象访问案例类成员



让我们从一个故事
开始我正在与一个虚构的俱乐部联系,人们在那里注册了一个聚会。经理要求我维护单独的成员名称和成员ID 列表。有一天,经理来找我,告诉了我这个问题。作为一个玩 scala 的开发人员,我给了他一个像上面提到的解决方案。


我想维护一个包含成员姓名及其 ID 的类。代码本质上非常粗糙,我绝对没有执行任何验证
第 1 步:我创建了一个名为NonEmptyFoo的类。
case class NonEmptyFoo(bar1:String,bar2:String)

在俱乐部喝啤酒时,我发现很少有人注册

第 2 步:添加用户(用户名,用户ID)都是字符串对象

val member1=NonEmptyFoo("member1","Foo_member1")
val member2=NonEmptyFoo("member2","Foo_member2")
val member3=NonEmptyFoo("member3","Foo_member3")


后来很多人注册,这对经理

来说真的很好第 3 步:用户名用户标识创建单独的列表

val (memName,memId)=clubMembers map(x=>(x.bar1,x.bar2)) unzip

呜! 我的解决方案似乎有效,除非有一天经理来告诉我;

"唰!人们非常兴奋,有时他们甚至没有输入数据就注册;我无法获得成员名称及其 ID 的正确列表,因为该列表有许多空字段。这让我很紧张。
我向俱乐部经理保证,第二天会为他提供一个强有力的解决方案。
我想
到了两件事1.如果我从头开始编写代码,我需要删除旧代码,并且新代码可能无法读取
2.我需要保持代码的可读性,并使它以一种新开发人员可以轻松维护新代码并从中添加/删除功能的方式进行
晚上我想给它添加抽象。我添加了以下代码
步骤 1为具有有效条目的用户创建了具有非空Foo的特征Foo,为具有无效条目的用户创建了具有EmptyFoo

的特征
     trait Foo
         case class EmptyFoo() extends Foo
         case class NonEmptyFoo(bar1:String,bar2:String) extends Foo

     object Foo{
       def apply(bar1:String,bar2:String)= (bar1,bar2) match{
        case (x,y)=>if(x.isEmpty||y.isEmpty) EmptyFoo() else NonEmptyFoo(x,y)
        case _=> EmptyFoo()
      }
   }

上面的代码有好处。首先,我能够验证具有有效条目的用户和具有无效条目的用户。其次,我将空的和非空的Foo抽象为仅Foo,以便可以轻松地将新方法添加到Foo中,从而在子类中实现,从而隐藏内部实现。
当用户输入有效数据时,如下所示

val mamber1=Foo("member1","Foo_member1")

工作表上的输出显示为

member1: Product with Serializable with Foo = NonEmptyFoo(member1,Foo_member1)

并且,当有人错过输入下面给出的字段之一时

val member2=Foo("member2","")

工作表上的输出显示为

member2: Product with Serializable with Foo = EmptyFoo()

有趣!! 它有效...
请耐心等待;
我能够执行抽象,并能够提出一个最小但良好的解决方案。但是,当我编写代码时,我遇到了真正的问题,如下所示

val member1=Foo("member1","Foo_member1")
val member2=Foo("member2","Foo_member2")
val member3=Foo("member3","Foo_member3")
val clubMembers=List(member1,member2,member3)
//heres where the problem occurs
val (memName,memId)=clubMembers map(x=>(x.bar1,x.bar2)) unzip

嗖!我被困在这里,因为编译器在下面给出的lambda表达式中

x=>(x.bar1,x.bar2)

无法识别栏 1栏 2

但是,此解决方案效果很好;

    val member1=NonEmptyFoo("member1","Foo_member1")
    val member2=NonEmptyFoo("member2","Foo_member2")
    val member3=NonEmptyFoo("member3","Foo_member3")
    val clubMembers=List(member1,member2,member3)
    //heres where the problem occurs
    val (memName,memId)=clubMembers map(x=>(x.bar1,x.bar2)) unzip

显然,该解决方案违反了抽象,因为我显式使用内部类名,而我应该使用特征的名称,根据验证,编译器应根据内部类推断需要对对象进行初始化。

您能否建议新解决方案可能存在什么问题。
编译器无法识别 bar1 和 bar2 的原因将不胜感激。
是的,替代解决方案确实存在,但我很乐意提出现有解决方案的建议,并且可能会遵循完全由您自行决定的替代解决方案。

提前感谢您的帮助!

推断的

clubMembers类型是List[Foo](即使具体元素是NonEmptyFoo的实例),并且由于Foo没有bar1bar2字段,因此您无法在映射调用中访问它们。一种可能的解决方案是将bar1bar2添加到Foo

sealed abstract class Foo(val bar1: String, val bar2: String)
case object EmptyFoo extends Foo("", "")
case class  NonEmptyFoo(override val bar1: String, override val bar2: String) extends Foo(bar1, bar2)
object Foo {
  def apply(bar1: String, bar2: String): Foo = {
    if (bar1.isEmpty || bar2.isEmpty) EmptyFoo else NonEmptyFoo(bar1, bar2)
  }
}

最新更新