文章目录
我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=3e60fnr5m3uo0
尾随 Lambda - Trailing Lambda 语法 : 满足如下两个条件 , 可以 使用 尾随 Lambda 语法 ;
那么可以 将最后一个参数 放在 括号外面 , 括号外使用 Lambda 表达式作为参数 ;
使用 尾随 Lambda 语法 可以使代码 更简洁 , 提高代码可读性 ;
示例说明 :
下面的函数 的最后一个参数 是 函数类型 ;
fun foo(x: Int, f: (Int) -> Int) {
val result = f(x)
println(result)
}
调用 foo 函数时 , 第二个参数是函数类型 , 并且该参数是函数的最后一个参数 ,
那么可以 使用 尾随 Lambda 语法 , 将 函数参数 移到括号外面 使用 Lambda 表达式表示 ;
正常调用方式如下 : 函数参数 放在 括号内进行传递 ;
foo(5, { x -> x * x })
使用 尾随 Lambda 语法 的调用方式 : 将第二个函数参数提取到括号外面 , 也就是将 Lambda 表达式 写在括号的外部 ;
foo(5) {
x -> x * x
}
在使用 Kotlin 开发时 , 经常遇到这种情况 , 最后一个函数是匿名内部类 , 匿名内部类中只实现了一个函数 , 此时使用 Lambda 表达式替代该 匿名内部类 ;
如 : 为按钮添加点击事件 , 对应的 Java 代码是
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 点击事件
}
});
翻译成 Kotlin 代码后为 : 使用对象表达式
button.setOnClickListener(object : View.OnClickListener {
override fun onClick(view: View) {
// 点击事件
}
})
更进一步简写为 :
button.setOnClickListener {
// 点击事件
}
Kotlin 中的 对象表达式 ,
object : View.OnClickListener {
override fun onClick(view: View) {
// 点击事件
}
}
对应的就是 Java 中的 匿名内部类 ;
new View.OnClickListener() {
@Override
public void onClick(View view) {
// 点击事件
}
}
Lambda 表达式 其本质 就是 函数类型 的 匿名对象 , 也是一个实例对象 , 在堆内存中分配相应的空间 ;
在下面的代码中 , 使用 对象表达式 创建了匿名对象 , 该匿名类实现了 View.OnClickListener 接口 , 并实现了其中的 onClick 函数 ;
object : View.OnClickListener {
override fun onClick(view: View) {
// 点击事件
}
}
符合以下两个条件 :
可以 省略掉 匿名内部类 也就是 对象表达式的定义 , 直接使用 接口中的函数 类型对象 , 也就是 Lambda 表达式 / 匿名函数 / 闭包 来替代该 接口类型 变量 ;
View 组件设置 按钮点击事件 的函数原型如下 : View#setOnClickListener 函数 接收一个 OnClickListener 实例对象作为参数 ;
/**
* 注册一个回调,以便在单击此视图时调用。如果这个视图是不可点击的,它就变成了可点击的。
*
* @param l 将运行的回调
*
* @see #setClickable(boolean)
*/
public void setOnClickListener(@Nullable OnClickListener l) {
if (!isClickable()) {
setClickable(true);
}
getListenerInfo().mOnClickListener = l;
}
而 OnClickListener 是一个接口 , 接口中只有一个方法 ;
/**
* 在单击视图时调用回调的接口定义。
*/
public interface OnClickListener {
/**
* 当视图被单击时调用。
*
* @param v 被单击的视图。
*/
void onClick(View v);
}
下面是 IntelliJ IDEA 中 , 为 View 组件设置 点击事件 时 , 输入 setOnClickListener 出现的代码提示 ;

View#setOnClickListener 可以设置两种参数 :
// 添加按钮点击事件 , 设置一个 对象表达式 表示 OnClickListener 子类
// 作为点击事件
textView.setOnClickListener(object : OnClickListener{
override fun onClick(v: View?) {
Log.i("TAG", "按钮点击事件")
}
})
// 添加按钮点击事件 , 设置一个 OnClickListener#onClick 函数类型的 Lambda 表达式
// 作为点击事件
textView.setOnClickListener {
Log.i("TAG", "按钮点击事件")
}
如果设置了 OnClickListener#onClick 函数类型的 Lambda 表达式 , 其 Lambda 表达式类型为
(View) -> Unit
传入 View 类型实例对象 , 返回值为 void , 对应的就是 OnClickListener 接口中的 void onClick(View v); 函数类型 ;
如果 在 setOnClickListener 函数中设置了 (View) -> Unit 类型的 Lambda 表达式 ,
Kotlin 编译时会查找 setOnClickListener 函数真正接收的是 OnClickListener 接口实例对象 ,
传入一个 Lambda 表达式 , 会自动为其创建 OnClickListener 接口对应的匿名内部类 ,
并且将该 Lambda 表达式作为该匿名内部类的函数实体 ;
如果 传入的 Lambda 表达式类型 , 不符合 接口中的唯一的函数类型 ,
也就是再该示例中 Lambda 表达式类型不是 (View) -> Unit 类型的 , 就会在编译时报错 ,
报错信息如下 :
'return' is not allowed here

it:View! , 如果设置成 it:String , 就会报如下错误 ;Type mismatch.
Required:
((View!) → Unit)?
Found:
(String) → Unit
Expected parameter of type View!

总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
我脑子里浮现出一些关于一种新编程语言的想法,所以我想我会尝试实现它。一位friend建议我尝试使用Treetop(Rubygem)来创建一个解析器。Treetop的文档很少,我以前从未做过这种事情。我的解析器表现得好像有一个无限循环,但没有堆栈跟踪;事实证明很难追踪到。有人可以指出入门级解析/AST指南的方向吗?我真的需要一些列出规则、常见用法等的东西来使用像Treetop这样的工具。我的语法分析器在GitHub上,以防有人希望帮助我改进它。class{initialize=lambda(name){receiver.name=name}greet=lambda{IO.puts("He
在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信
我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择