Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.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
Scala 对某些属性进行编译时检查_Scala_Types - Fatal编程技术网

Scala 对某些属性进行编译时检查

Scala 对某些属性进行编译时检查,scala,types,Scala,Types,给定以下scala代码: sealed trait Color case object Red extends Color case object Blue extends Color sealed trait Car { def isBroken: Boolean def color: Color } 我如何定义这种方法: def fixBrokenRedCar(c: A): B 也就是说,A和B应该是什么?该方法应仅接受同时为红色和isbreak=true的车辆。否则它将发出编

给定以下scala代码:

sealed trait Color
case object Red extends Color
case object Blue extends Color

sealed trait Car {
  def isBroken: Boolean
  def color: Color
}
我如何定义这种方法:

def fixBrokenRedCar(c: A): B

也就是说,
A
B
应该是什么?该方法应仅接受同时为
红色
isbreak=true
的车辆。否则它将发出编译错误。此外,输出
B
应该包含关于其类型的信息,这样,如果我创建另一个方法
destroyRedCar(c:B)
,并将其应用于输出,它应该进行相应的编译。

您应该将数据移动到类型级别,然后:

trait Bool
trait T extends Bool
trait F extends Bool

trait Color
trait Red extends Color
trait Blue extends Color

trait Car[Clr <: Color, Brkn <: Bool]

def fixBrokenCar[Cr <: Car[Red, T]](c: Cr) = new Car[Red, F]{}

scala> fixBrokenCar(new Car[Blue, T]{})
<console>:16: error: inferred type arguments [Car[Blue,T]] do not conform to method fixBrokenCar's type parameter bounds [Cr <: Car[Red,T]]
              fixBrokenCar(new Car[Blue, T]{})
              ^
<console>:16: error: type mismatch;
 found   : Car[Blue,T]
 required: Cr
              fixBrokenCar(new Car[Blue, T]{})
                           ^

scala> fixBrokenCar(new Car[Red, T]{})
res3: Car[Red,F] = $anon$1@67d9a642

您还可以定义一些
defcopy[C我假设您可以更改您的类结构

实现所需的一种方法是使用类型级编程。这里有一个非常好的堆栈溢出帖子:

下面是一些基于原始代码的示例代码,演示了如何在Scala中使用类型系统实现这一点

/* 
 * Color traits I've left the same except converted the objects 
 * to classes. This would work just as well with traits. It might 
 * even be better if the Colors such as Red and Blue are traits
 * themselves that extend Color, I'm still just learning this 
 * method myself.
 */
sealed trait Color
class Red extends Color
class Blue extends Color

/* New trait to represent whether something is broken or not */
sealed trait IsBroken    
class Broken extends IsBroken
class NotBroken extends IsBroken

/* Change Car trait to have two type parameters, broken and color */   
trait Car[T <: Color, S <: IsBroken]

/* fixBrokenCar signature includes whether a car is broken and it's color */
def fixBrokenRedCar(c: Car[Red, Broken]): Car[Red, NotBroken]
    = new Car[Red, NotBroken]{}

val brokenRedCar = new Car[Red, Broken]{}
val fixedRedCar = new Car[Red, NotBroken]{}
val brokenBlueCar = new Car[Blue, Broken]{}

/* Compiles */
fixBrokenRedCar(brokenRedCar)

/* Doesn't compile */
fixBrokenRedCar(fixedRedCar)

/* Doesn't compile */
fixBrokenRedCar(brokenBlueCar)
/*
*颜色特征除了转换对象外,我没有改变
*对班级来说,这同样适用于特质。它可能
*如果红色和蓝色都是特征,那就更好了
*他们自己延伸颜色,我仍然只是在学习这个
*我自己。
*/
密封特性色
类红色扩展颜色
类蓝色扩展颜色
/*表示某物是否损坏的新特征*/
密封件坏了
类断开扩展是断开的
类notbreak扩展为isbreak
/*将Car trait更改为具有两个类型参数,breaked和color*/

trait Car[T如果我创建
fixBrokenCar(新车[Red,T]{def brand=“honda”})
,我就失去了
brand
。有什么办法吗?很简单,只需添加
trait Car[Clr btw,当scala为您生成结构类型时,您不会在
fixBrokenCar
内松开它:
Car[Red,F]{def brand:String}
-您将其松开
destroyRedCar
,因为它忽略了
品牌
属性-无论哪种方式,trait中的明确定义都将有助于说明我创建了
trait BrandedCar[Clr]
trait Car[Clr <: Color, Brkn <: Bool] { 
   type Copy[C <: Color, B <: Bool] <: Car[C,B] // define "copy" type-method
}

trait BrandedCar[Clr <: Color, Brkn <: Bool] extends Car[Clr, Brkn] {
   type Copy[C <: Color, B <: Bool] = BrandedCar[C, B] // implement "copy" type-method
   def brand: String = "default"
}

def fixBrokenCar[Cr <: Car[Red, T]](c: Cr) = c.asInstanceOf[Cr#Copy[Red, F]]

def checkBrandedCar(c: BrandedCar[_, F]) = true // accepts only branded and fixed


scala> checkBrandedCar(new BrandedCar[Red, F]{})
res10: Boolean = true

scala> checkBrandedCar(new Car[Red, F]{})
<console>:15: error: type mismatch;
 found   : Car[Red,F]
 required: BrandedCar[?, F]
              checkBrandedCar(new Car[Red, F]{})
                              ^

scala> checkBrandedCar(fixBrokenCar(new BrandedCar[Red, T]{}))
res12: Boolean = true
/* 
 * Color traits I've left the same except converted the objects 
 * to classes. This would work just as well with traits. It might 
 * even be better if the Colors such as Red and Blue are traits
 * themselves that extend Color, I'm still just learning this 
 * method myself.
 */
sealed trait Color
class Red extends Color
class Blue extends Color

/* New trait to represent whether something is broken or not */
sealed trait IsBroken    
class Broken extends IsBroken
class NotBroken extends IsBroken

/* Change Car trait to have two type parameters, broken and color */   
trait Car[T <: Color, S <: IsBroken]

/* fixBrokenCar signature includes whether a car is broken and it's color */
def fixBrokenRedCar(c: Car[Red, Broken]): Car[Red, NotBroken]
    = new Car[Red, NotBroken]{}

val brokenRedCar = new Car[Red, Broken]{}
val fixedRedCar = new Car[Red, NotBroken]{}
val brokenBlueCar = new Car[Blue, Broken]{}

/* Compiles */
fixBrokenRedCar(brokenRedCar)

/* Doesn't compile */
fixBrokenRedCar(fixedRedCar)

/* Doesn't compile */
fixBrokenRedCar(brokenBlueCar)