简体   繁体   English

如何避免在Scala中使用asInstanceOf

[英]How to avoid using asInstanceOf in Scala

Currently my code needs class casting 目前我的代码需要类转换

val dataWriter: BytesDataWriter = createDataWriter

 def createDataWriter(p: SomeClass) =
    p.create_datawriter().asInstanceOf[BytesDataWriter]

The create_datawriter method will return the superclass DataWriter. create_datawriter方法将返回超类DataWriter。 Instead of casting it using asInstanceOf , I tried this approach 我尝试了这种方法,而不是使用asInstanceOf进行转换

val dataWriter: BytesDataWriter = createDataWriter(p)  match {
      case writer: BytesDataWriter => writer
      case _ => throw new ClassCastException
    }

This is too verbose, and in case case does not work. 这太冗长了,如果情况不起作用。 Is there a better alternative to class casting? 是否有更好的替代类铸造?

You would use the second approach in case you can do something with a non- BytesDataWriter result, or to get a better error message: 如果您可以使用非BytesDataWriter结果执行某些 BytesDataWriter ,或者为了获得更好的错误消息,您将使用第二种方法:

val dataWriter: BytesDataWriter = p.create_datawriter() match {
  case writer: BytesDataWriter => writer
  case other => throw new Exception(s"Expected p to create a BytesDataWriter, but got a ${other.getClass.getSimpleName} instead!")
}

Otherwise, use asInstanceOf . 否则,请使用asInstanceOf

The answer from Alexey Romanov is a good advice for your specific situation. Alexey Romanov的答案对于您的具体情况是一个很好的建议。 Alternatively you could try to avoid this situation by changing the sctructure of the surrounding code. 或者,您可以通过更改周围代码的结构来避免这种情况。

Can your problem be reformulated? 你的问题可以重新制定吗?

When you are using a class and instantiate it, it looks like you are implementing some kind of configurable dependency handling. 当您使用类并实例化它时,看起来您正在实现某种可配置的依赖项处理。 This is a complex problem, but fortunately there are some good solutions for this: 这是一个复杂的问题,但幸运的是有一些很好的解决方案:

Dependency injection 依赖注入

You could use some kind of dependency injection and inject the needed ByteDataWriter with the specialized type. 您可以使用某种依赖注入并使用专用类型注入所需的ByteDataWriter Look at the "Robot Leg" example described in the Google Guice FAQ on how to deal with different variants of the same base class, and on how to deal with generics . 查看Google Guice FAQ中描述的“机器人腿”示例,了解如何处理同一基类的不同变体,以及如何处理泛型 This might help you to avoid your problem with DataWriter and ByteDataWriter . 这可以帮助您避免DataWriterByteDataWriter问题。

Duck typing 鸭打字

You can also access your DataWriter with a protocol (or in Scala speak: a strucutral type ). 您还可以使用协议访问DataWriter (或者在Scala中使用: 结构类型 )。 Structural typs will not be checked at compile time, so no need for a class cast. 在编译时不会检查结构类型,因此不需要类强制转换。

Cake pattern 蛋糕模式

Or you can handle you dependencies using a Scala specialty: The cake pattern . 或者您可以使用Scala专业处理依赖项: 蛋糕模式 With this pattern you can compose your class just as needed. 有了这种模式,您可以根据需要撰写课程。 You can design the class needing the ByteDataWriter completely type safe. 您可以设计需要ByteDataWriter的类完全类型安全。 The compiler will then make sure, that it can only combined with the correct class. 然后编译器将确保它只能与正确的类组合。 No need for a class cast. 不需要课堂演员。 The disadvantage is, that you cannot reconfigure the dependencies using a config file. 缺点是,您无法使用配置文件重新配置依赖项。 But usually this is not necessary, because the supported variants are well known at compile time. 但通常这不是必需的,因为支持的变体在编译时是众所周知的。

Conclusion: Try to reformulate when possible 结论:尽可能尝试重新配方

If you have the option, consider to re-design your code using one of the methods described above, to get rid of the class cast. 如果您有选项,请考虑使用上述方法之一重新设计代码,以摆脱类强制转换。 It is very likely that you will have the same problem on many other places in your code. 很可能您在代码中的许多其他位置都会遇到同样的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM