我正在学习 Kotlin。我的代码如下:
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
decoupler.attachNotifier(this)
if(activity is ScreenRouter) {
decoupler.attachRouter(activity)
}
}
attachRouter() 方法:
fun attachRouter(router: ScreenRouter?) {
this.router = router
}
如 documentation 中所述, kotlin 在使用 is 运算符检查后自动转换为类型。所以,我希望它会起作用。但相反,编译错误让我感到困扰:
智能转换到 ScreenRouter 是不可能的,因为 activity 是一个具有开放或自定义 getter 的属性。
我认为错误可能是因为 Activity 可以为空,所以我尝试了:
if(activity!=null && activity is ScreenRouter) {
decoupler.attachRouter(activity)
}
但它不起作用,编译失败并出现同样的错误。
但是,以下代码可以正常工作:
if(activity is ScreenRouter) {
decoupler.attachRouter(activity as ScreenRouter)
}
没关系,但上述错误似乎无法解释智能广播失败的原因。我不是 Kotlin 专家,我只是学习 Kotlin 的初学者。我在任何地方都没有找到任何文档。这类错误描述让 Kotlin 难以学习。谁能简单的解释一下?
最佳答案
这里的关键点是 open 属性或具有自定义 getter 的属性不能保证在连续调用时返回相同的值。
因此,编译器无法确定,一旦从属性接收到的值被检查过,就可以安全地假设如果再次调用它会返回相同的对象甚至是相同类型的对象。
示例(虽然非常简化和综合):
open class Base {
open val value: List<Int> = ArrayList()
}
val b : Base = foo()
fun printArrayList(list: ArrayList<Int>) { /* ... */ }
if (b.value is ArrayList) { // first call
printArrayList(b.value) // second call, smart cast is impossible
}
这段代码不会编译,因为 printArrayList() 需要一个 ArrayList 并且 b.value 是 open -- 这就是你在代码中得到的。现在,让我们组成一个派生类来演示可能出错的地方:
class Derived : Base() {
private var counter = 0
override val value: List<Int>
get() {
++counter
return if (counter % 2 == 0)
ArrayList() else
LinkedList()
}
}
val b = Derived()
println(b.value.javaClass) // class java.util.LinkedList
println(b.value.javaClass) // class java.util.ArrayList
这里很清楚,如果一个属性是open,它可以被覆盖,连续调用它会返回不同的值。在带有 printArrayList() 的示例中,有两个这样的调用。这就是智能 Actor 不安全的原因。具有自定义 getter 的属性也是如此。
您在 if block 内执行 as-cast 的示例有效,因为如果属性返回,该转换将失败并抛出 ClassCastException在第二次调用时使用不兼容类型的不同值,这将保持类型安全。
相反,如果一个 val 属性不是 open 并且有一个默认的 getter,它只返回 backing field 的值。 (在这种情况下是 final),编译器可以安全地执行智能转换:如果多次获取属性的值,它肯定是相同的。
另一种方法是获取一次值,将其存储在局部变量中并多次使用它,而不是再次使用该属性:
val list = b.value
if (list is ArrayList) {
printArrayList(list) // smart cast to ArrayList
}
现在,无论一个属性是否open,只有一次调用它的getter,然后代码使用调用返回的值进行操作。既然不能改变,这里就可以智能施法了。
关于java - Smartcast 是不可能的,因为属性有开放的或自定义的 getter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41086296/
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog
对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些