Void和交集类型的奇怪行为

时间:2015-08-06 18:37:31

标签: scala covariance

这是预期的行为吗?

scala> val l: List[Void] = "I'm void".asInstanceOf[String with Void] :: Nil
l: List[Void] = List(I'm void)

l识别为List[Void]并将String显示为第一个元素是否有效?

2 个答案:

答案 0 :(得分:2)

从某种意义上说,这是完全有效的,并不是class ProfilesController < ApplicationController before_action :authenticate_user!, except: [:show] before_action :find_profile_by_id, only: [:show, :edit, :update] after_filter :destroy_user!, only: [:destroy] def index if @profile.blank? render :new else render :show end end def new @profile = current_user.profiles.build @user = current_user.where('email=?') end def create @profile = current_user.profiles.build(profile_params) if @profile.save redirect_to @profile else render :new end end def show end def edit end def update if @profile.update(profile_params) redirect_to @profile else render :edit end end def destroy @user.destroy @profile.destroy redirect_to root_path end private def profile_params params.require(:profile).permit(:name, :email, :bio, :location, :homepage, :work) end def find_profile_by_id @profile = Profile.find(params[:id]) end def destroy_user! @user = User.find(params[:id]) end end 特有的。单独Void

"I'm void".asInstanceOf[String with Void]

这是有效的,因为我们要求编译器说ClassCastExceptionval l: List[Void] = "I'm void".asInstanceOf[String with Void] :: Nil 的实例,而"I'm void"String with Void的子类型},这意味着我们可以片刻有一个String with Void,因为Void然而,如果我们尝试访问List[Void]的头部,我们预计会有List[String with Void] <: List[Void],原来的List[Void]不是。{/ p>

Void

它似乎首先起作用,因为所有内容都有String方法,因此不需要将其视为scala> l.head java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Void 以外的其他内容。

如果我们使用toString进行尝试,也会发生同样的事情。

Any

String with Int将很高兴存在,直到现实开始,我们才意识到它实际上不是scala> val int = "I'm an Int".asInstanceOf[String with Int] int: String with Int = I'm an Int scala> int % 2 java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer ,并且没有String with Int方法。< / p>

答案 1 :(得分:2)

稍微扩展@ m-z的答案,解释为什么 .asInstanceOf[String with Void]不会抛出。我们需要区分Scala中存在的内容以及JVM字节码中存在的内容。特别是,字节码不支持像String with Void这样的交集类型,因此无法转换为它。因此,为.asInstanceOf[String with Void]发出的字节码实际上与.asInstanceOf[String]相同;但是当编译器看到此类型的值用作Void时,它会插入额外的强制转换。

这就是为什么你不能使用List[Int]区分具有不同参数的通用类型(如List[String]isInstanceOf)的原因:就字节码而言,类型是相同的。