Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.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
Kotlin 为什么是?不';是否在if块内强制转换变量?_Kotlin_Casting - Fatal编程技术网

Kotlin 为什么是?不';是否在if块内强制转换变量?

Kotlin 为什么是?不';是否在if块内强制转换变量?,kotlin,casting,Kotlin,Casting,我编写了以下代码: class MyRoamable { var r: Roamable = Wolf() fun myFunction() { var x = r as? Wolf if (r as? Wolf != null) { r.wolfNoise() } } } open class Roamable { fun roam():String {

我编写了以下代码:

 class MyRoamable
{
    var r: Roamable = Wolf()
    fun myFunction()
    {
        var x = r as? Wolf
        if (r as? Wolf != null)
        {
            r.wolfNoise()
        }
    }
}

open class Roamable
{
    fun roam():String
    {
        return "awhooooooo"
    }
}

class Wolf:Roamable()
{
    fun wolfNoise():String
    {
        return "wolf Noise"
    }
}





I can't understand why the following doesn't work:
if(r as?Wolf!=null) { r、 沃尔夫噪音() }

我敢肯定,我在过去做过这样的演员。错误是: 未解析参考:wolfNoise

为什么它继续把r当作可漫游者,而不是狼

我过去的工作方式是:

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    if (holder as? ViewHolder != null) {
        
        holder.homeTeamTextView.text = homeTeam
        holder.awayTeamTextView.text = awayTeam
        holder.homeTeamTextView.setTypeface(null,Typeface.NORMAL)
        holder.awayTeamTextView.setTypeface(null,Typeface.NORMAL)
        if (holder.winDescription != null)
        {
            holder.winDescription.text = gameWindowDescription
        }
        else
        {
            holder.winDescription.text = ""
        }


  class ViewHolder (view : View, onRecyclerItemClickListener: OnRecyclerItemClickListener?) : RecyclerView.ViewHolder(view)
{
    val homeTeamTextView : TextView = view.findViewById(R.id.home_club_tv)
    val awayTeamTextView : TextView = view.findViewById(R.id.away_club_tv)
    val homeTeamImageView : ImageView = view.findViewById(R.id.home_club_iv)
    val awayTeamImageView : ImageView = view.findViewById(R.id.away_club_iv)
    val timeTextView : TextView = view.findViewById(R.id.games_status_tv)
    val scoreTextView : TextView = view.findViewById(R.id.score_tv)
    val winDescription: TextView = view.findViewById(R.id.game_window_description)
从那时起,我可以从视图中获取所有数据
如果(holder as?ViewHolder!=null)成功

对于Kotlin的编译器来说太复杂:)我认为这样写会更习惯:

fun myFunction(){
val x=r as?Wolf
x?.wolfNoise()
}

在使用视图持有者的示例中,不强制转换变量。您只需检查它是否为null(对于Kotlin的编译器来说太复杂了:)我认为这样写会更习惯:

fun myFunction(){
val x=r as?Wolf
x?.wolfNoise()
}

在使用视图持有者的示例中,不强制转换变量。您只需检查它是否为空

智能强制转换不是偶然发生的,编译器中必须明确支持每个模式。如果将
r
设为局部变量

fun myFunction() {
    var r: Roamable = Wolf()
    if (r as? Wolf != null) {
        r.wolfNoise()
    }
}
val

val r: Roamable = Wolf()
fun myFunction() {
    if (r as? Wolf != null) {
        r.wolfNoise()
    }
}
它起作用了

在这方面,参数被视为
val
局部变量,因此
override-fun-onBindViewHolder(holder:RecyclerView.ViewHolder,position:Int)
示例实际上是两者兼而有之

在您的情况下,如果两个线程都可以看到
Roamable
的实例,并且其中一个执行了
myFunction
,那么另一个可以在
r之后更改
r
?对Wolf
进行了评估,并在
r.wolfNoise()
被评估之前进行了评估

你可以说:但是这个程序没有任何线程!但是编译器必须编译
Roamable
,这样它也可以在其他程序中使用

编辑:不知何故,我误读了你的例子,认为你有

var r: Roamable = Wolf()
fun myFunction() {
    var x = r as? Wolf
    if (r as? Wolf != null) {
        r.wolfNoise()
    }
}
在函数内部,而不是类内部。下面的解释将适用于这种情况

如果在中使用外部作用域中的局部变量(而不是属性!)
var
,如

编译器必须将其转换为

private class RoamableHolder(var value: Roamable)

private fun outer_myFunction(holder: RoamableHolder) {
    if (holder.value as? Wolf != null) {
        holder.value.wolfNoise()
    }
}

fun outer() {
    val r_holder = RoamableHolder(Wolf())
    outer_myFunction(r_holder)
}
在幕后,因为JVM没有本地方法。您可以看到它将如何允许
myFunction
更改
r
的值,并在
outer
中显示该值

智能转换不能与该代码一起工作,因为您不能智能转换
var
properties,因此它也不能与原始代码一起工作

但是,如果
outer
中的
r
val
而不是
var
,则不需要
RoamableHolder
,并且翻译更简单:

private fun outer_myFunction(r: Roamable) {
    if (r as? Wolf != null) {
        r.wolfNoise()
    }
}

fun outer() {
    val r: Roamable = Wolf()
    outer_myFunction(r)
}

智能强制转换不是偶然发生的,每个模式都必须在编译器中得到显式支持。如果将
r
设为局部变量

fun myFunction() {
    var r: Roamable = Wolf()
    if (r as? Wolf != null) {
        r.wolfNoise()
    }
}
val

val r: Roamable = Wolf()
fun myFunction() {
    if (r as? Wolf != null) {
        r.wolfNoise()
    }
}
它起作用了

在这方面,参数被视为
val
局部变量,因此
override-fun-onBindViewHolder(holder:RecyclerView.ViewHolder,position:Int)
示例实际上是两者兼而有之

在您的情况下,如果两个线程都可以看到
Roamable
的实例,并且其中一个执行了
myFunction
,那么另一个可以在
r之后更改
r
?对Wolf
进行了评估,并在
r.wolfNoise()
被评估之前进行了评估

你可以说:但是这个程序没有任何线程!但是编译器必须编译
Roamable
,这样它也可以在其他程序中使用

编辑:不知何故,我误读了你的例子,认为你有

var r: Roamable = Wolf()
fun myFunction() {
    var x = r as? Wolf
    if (r as? Wolf != null) {
        r.wolfNoise()
    }
}
在函数内部,而不是类内部。下面的解释将适用于这种情况

如果在中使用外部作用域中的局部变量(而不是属性!)
var
,如

编译器必须将其转换为

private class RoamableHolder(var value: Roamable)

private fun outer_myFunction(holder: RoamableHolder) {
    if (holder.value as? Wolf != null) {
        holder.value.wolfNoise()
    }
}

fun outer() {
    val r_holder = RoamableHolder(Wolf())
    outer_myFunction(r_holder)
}
在幕后,因为JVM没有本地方法。您可以看到它将如何允许
myFunction
更改
r
的值,并在
outer
中显示该值

智能转换不能与该代码一起工作,因为您不能智能转换
var
properties,因此它也不能与原始代码一起工作

但是,如果
outer
中的
r
val
而不是
var
,则不需要
RoamableHolder
,并且翻译更简单:

private fun outer_myFunction(r: Roamable) {
    if (r as? Wolf != null) {
        r.wolfNoise()
    }
}

fun outer() {
    val r: Roamable = Wolf()
    outer_myFunction(r)
}

在可漫游的示例中,
r
是一个属性。
var
属性永远不能是智能强制转换,因为编译器不能保证在键入check和尝试对其执行操作(调用其函数、将其作为参数传递、将其分配给变量等)时,属性将返回相同的值。使用自定义getter的
val
属性也是如此

现在,您可能没有以多线程的方式使用这个类,因此您知道强制转换是安全的,但是编译器没有足够的智能来检查这一点,因此您必须手动强制转换。我认为这个编译器规则的原因是它太复杂,无法检查。也许这是可行的,但是一些编译器限制已经到位,所以编译速度会很快,而不是因为逻辑上的不可能性

在ViewHolder示例中,
holder
是一个函数参数,因此其他线程不可能修改它。在Kotlin中,与Java不同,函数参数是常量,因此根本不可能修改它们。因此,使用函数参数总是可以进行智能转换


您还可以使用本地
var
变量进行智能强制转换,因为编译器可以在本地代码中看到,在检查和使用值之间,变量没有被重新分配。如果在闭包中使用局部变量,那么它就不再是智能可转换的,因为现在它有点像一个属性:它可以从其他地方修改,因此编译器不能再保证它的类型。

在可漫游的示例中,