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