Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Scala只接受列表中的字符串或Int泛型case类_Java_Scala - Fatal编程技术网

Java Scala只接受列表中的字符串或Int泛型case类

Java Scala只接受列表中的字符串或Int泛型case类,java,scala,Java,Scala,我有一个case类,定义如下 case class ChooseBoxData[T](index:T, text:String) 是否可以声明一个列表,使列表只接受ChooseBoxData[String]和ChooseBoxData[Int]的类型 我所期望的是: val specialList:List[some type declaration] = List( ChooseBoxData[String]("some string","some string"),/* allow,

我有一个case类,定义如下

case class ChooseBoxData[T](index:T, text:String)
是否可以声明一个列表,使列表只接受ChooseBoxData[String]和ChooseBoxData[Int]的类型

我所期望的是:

val specialList:List[some type declaration] = List(
  ChooseBoxData[String]("some string","some string"),/* allow, because is ChooseBoxData[String]*/
  ChooseBoxData[Int](12,"some string"), /* also allow, because is ChooseBoxData[Int]*/
  ChooseBoxData[Boolean](true,"some string")/* not allow type other than ChooseBoxData[String] or ChooseBoxData[Int]*/
)

以下是我的想法:

首先,我们创建以下代数数据类型(ADT):

并定义
chooseboxdata
,如下所示:

case class ChooseBoxData(index : StringInt, text : String)
然后我们定义以下隐式,将范围中的
Int
String
转换为定义的ADT:

object CBImplicits {
  implicit def conv(u : String) = Stringy(u)
  implicit def conv2(u : Int) = Inty(u)
}
现在,我们可以执行问题中的要求。以下是一个例子:

import CBImplicits._

val list = List(ChooseBoxData("str", "text"),
ChooseBoxData(1, "text"),
ChooseBoxData(true, "text"))
尝试运行上述命令时,编译器会抱怨类型不匹配。但这将编译并运行:

List(
  ChooseBoxData("str", "text"),
  ChooseBoxData(1, "text"),
  ChooseBoxData(12, "text2"))
其结果是:

a: List[ChooseBoxData] = 
List(ChooseBoxData(Stringy(str),text), ChooseBoxData(Inty(1),text), ChooseBoxData(Inty(12),text2))
这将保留
索引
类型信息(当然是包装在
StringInt
超类型中),稍后可以使用单个元素的模式匹配轻松提取这些信息

删除所有元素的包装器也很容易,但它会导致
索引
类型变成
Any
,这是我们所期望的,因为
Any
是Scala类层次结构中
String
Int
的最低共同祖先

编辑:使用

因此,它允许编译,但会将无效实例替换为
None
(如果需要,可以使用它抛出运行时错误),或者您可以使用以下方法直接筛选所需的实例:

list.flatMap(x => x.cast[ChooseBoxData[Int]])
//results in:
List[ChooseBoxData[Int]] = List(ChooseBoxData(1,txt))

您可以在case类之上构建额外的约束

import language.implicitConversions

case class ChooseBoxData[T](index:T, text:String)

trait MySpecialConstraint[T] {
  def get: ChooseBoxData[T]
}

implicit def liftWithMySpecialConstraintString(cbd: ChooseBoxData[String]) =
  new MySpecialConstraint[String] {
    def get = cbd
  }

implicit def liftWithMySpecialConstraintInt(cbd: ChooseBoxData[Int]) =
  new MySpecialConstraint[Int] {
    def get = cbd
  }


// Now we can just use this constraint for out list 
val l1: List[MySpecialConstraint[_]] = List(ChooseBoxData("A1", "B1"), ChooseBoxData(2, "B2"))

你为什么不能这样做:

object solution extends App {

  case class ChooseBoxData[T](index: T, text: String) extends GenericType[T]

  trait GenericType[T] {
    def getType(index: T, text: String): ChooseBoxData[T] = ChooseBoxData[T](index, text)
  }

  val specialList = List(
    ChooseBoxData[String]("some string", "some string"),
    ChooseBoxData[Int](12, "some string"), 
    ChooseBoxData[Boolean](true, "some string")
  )

  println(specialList)
}

//output: List(ChooseBoxData(some string,some string), ChooseBoxData(12,some string), ChooseBoxData(true,some string))

可能是这样的:

trait AllowableBoxData  
object AllowableBoxData {
private of[T](cbd: ChooseBoxData[T]) = new ChooseBoxData(cbd.index, cbd.text) 
    with AllowableBoxData
  implicit def ofInt(cbd: ChooseBoxData[Int]) = of(cbd)
  implicit def ofString(cbd: ChooseBoxData[String]) = of(cbd)
}
现在你可以做像这样的事情

val list: List[ChooseBoxData[_] with AllowableBoxData] = List(ChooseBoxData("foo", "bar"), ChooseBoxData(0, "baz")
但不是
val list:list[AllowableBoxData]=list(选择boxdata(false,“baz”))

另外,如果您希望声明一个函数参数而不仅仅是一个变量,那么会有一个更优雅的解决方案:

trait CanUse[T]
implicit case object CanUseInt extends CanUse[Int]
implicit case object CanUseString extends CanUse[String]

def foo[T : CanUse](bar: List[ChooseBoxData[T]])

好。。。至少scala控制台在
val list=list(ChooseBoxData(“str”,“text”)、ChooseBoxData(1,“text”)、ChooseBoxData(true,“text”))方面没有问题。
@SarveshKumarSingh,对不起,我忘了添加如何定义case类。现在应该清楚了
index
只能是
StringInt
,它最终可以是字符串或Int。您好,感谢您的回答,第一个解决方案似乎不再允许我声明ChooseBoxData[Boolean],但我仍然需要它在其他类中,如果可能的话,我不希望使用过滤器,但目前看来,这似乎是最好的解决方案me@jialeko,使用无形状的解决方案返回布尔索引的
None
。因此,如果运行时异常有效,可以使用它抛出运行时异常。对于使用ADT的解决方案,我想您可以在不同的类中扩展基本特征,以允许在不同的位置使用不同的规则。@jialeko,例如,如果您注释掉
map
函数(
case\u=>None
)中的最后一行,您将得到一个匹配错误。您能解释一下用户如何获得
ChooseBoxData吗(Int,String)
或a
从最终列表中选择BoxData(String,String)
?模式匹配可以帮助实现这一点。为此,我不希望更改
案例类本身,因为它可能不受OP的控制。我尝试了
l1(0).get.index
我得到了:
res0:Any=A1
val ChooseBoxData(index:String,text)=l1(0)。get
我想值得注意的是,当要使用的类型是
MySpecialConstraint
时,这种方法是有效的
编译并运行。您好,谢谢您的回答,但我对您的解决方案有点困惑……您能否进一步解释一下它如何不允许ChooseBoxData[Boolean]在列表中?实际上它也允许!布尔值。我将更新答案以满足您的要求。对象定义中的方法不应该有
def
s吗?还有,如何从结果列表中提取
ChooseBoxData
s?是的,错过了
def
s,抱歉,不确定“如何提取…”是什么意思有几种方法,比如
list.head
或者
list.last
或者
list(123)
等等……我不能
list.head.index
或者
list.head.text
though@jrook啊,是的……您需要将其声明为
List[ChooseBoxData[\uux]with AllowableBoxData]
val list: List[ChooseBoxData[_] with AllowableBoxData] = List(ChooseBoxData("foo", "bar"), ChooseBoxData(0, "baz")
trait CanUse[T]
implicit case object CanUseInt extends CanUse[Int]
implicit case object CanUseString extends CanUse[String]

def foo[T : CanUse](bar: List[ChooseBoxData[T]])