如何在 kotlin 中简化此代码?
How can I make this code simpler in kotlin?
我自学了编程,然后决定使用 Kotlin。
我编写了一个解决三角形的简单程序,效果很好,但我的代码丑陋且重复。
你能帮我改进一下吗,任何建议都会有帮助,因为即使我的代码有效,它看起来也不正确。
private fun validateNumbers() {
if(binding.etHip.text.toString().isNotEmpty()){
Hip = (binding.etHip.text.toString()).toFloat()
}
if(binding.etAdj.text.toString().isNotEmpty()){
Adj = (binding.etAdj.text.toString()).toFloat()
}
if(binding.etOpp.text.toString().isNotEmpty()){
Opp = (binding.etOpp.text.toString()).toFloat()
}
if(binding.etAngle.text.toString().isNotEmpty()){
Angle = (binding.etAngle.text.toString()).toFloat()
}
}
private fun countSelected() {
binding.cbHyp.setOnCheckedChangeListener { compoundButton, b ->
if(binding.cbHyp.isChecked){
numberCB++
}
else{
numberCB--
}
}
binding.cbAdj.setOnCheckedChangeListener { compoundButton, b ->
if(binding.cbAdj.isChecked){
numberCB++
}
else{
numberCB--
}
}
binding.cbOpp.setOnCheckedChangeListener { compoundButton, b ->
if(binding.cbOpp.isChecked){
numberCB++
}
else{
numberCB--
}
}
binding.cbAngle.setOnCheckedChangeListener { compoundButton, b ->
if(binding.cbAngle.isChecked){
numberCB++
}
else{
numberCB--
}
}
}
这个怎么样?逻辑是一样的。它只是在语法上进行了简化。
private fun validateNumbers() = with(binding) {
if (etHip.text.toString().isNotEmpty()) Hip = (etHip.text.toString()).toFloat()
if (etAdj.text.toString().isNotEmpty()) Adj = (etAdj.text.toString()).toFloat()
if (etOpp.text.toString().isNotEmpty()) Opp = (etOpp.text.toString()).toFloat()
if (etAngle.text.toString().isNotEmpty()) Angle = (etAngle.text.toString()).toFloat()
}
private fun countSelected() = with(binding) {
setOf(cbHyp, cbAdj, cbOpp, cbAngle).forEach {
it.setOnCheckedChangeListener { if (it.isChecked) numberCB++ else numberCB-- }
}
}
对于这两个函数,您可以将它们包装在 with(binding)
中,这样您就不必一直写 binding.
对于 validateNumbers
,您可以使用 toFloatOrNull()
将值转换为 Float,或者如果它不作为 Float 求值则为 null(例如空字符串无效)。然后您可以使用 Elvis 运算符 ?:
来提供默认值。所以如果你不想改变这个值,它可以 return 本身。
此外,由于您重复执行此操作,因此您可以创建一个从 EditText 获取值的快捷方式。这是TextView的一种,所以你可以把它写成TextView的扩展。
private fun TextView.toFloatOrNull() = text.toString().toFloatOrNull()
private fun validateNumbers() = with(binding) {
Hip = etHip.toFloatOrNull() ?: Hip
Adj = etAdj.toFloatOrNull() ?: Adj
Opp = etOpp.toFloatOrNull() ?: Opp
Angle = etAngle.toFloatOrNull() ?: Angle
}
使用 countSelected()
因为他们都在他们的听众中做完全相同的事情,所以你可以给他们所有相同的听众。 lambda 中的第二个参数是它是否刚刚被检查,所以你也可以稍微简化一下逻辑。您可以使用 listOf(...).forEach
来获取它们。
fun countSelected() = with(binding) {
val listener = OnCheckedChangeListener { _ isChecked ->
if (isChecked) numberCB++ else numberCB--
}
listOf(cbHyp, cbAdj, cbOpp, cpAngle).forEach {
it.onCheckedChangeListener = listener
}
}
我还会将函数名称更改为更具描述性的名称。您的函数不计算某些东西...它正在设置复选框来计算它们自己。
注意,属性 和变量名按照惯例应以小写字母开头。这将使您的代码更易于阅读。大写首字母通常保留用于 class 和接口名称。 (它们也用于其他一些语言中的函数名称,但您不应该在 Kotlin 中这样做,否则它们会与构造函数调用混淆。)
我自学了编程,然后决定使用 Kotlin。
我编写了一个解决三角形的简单程序,效果很好,但我的代码丑陋且重复。
你能帮我改进一下吗,任何建议都会有帮助,因为即使我的代码有效,它看起来也不正确。
private fun validateNumbers() {
if(binding.etHip.text.toString().isNotEmpty()){
Hip = (binding.etHip.text.toString()).toFloat()
}
if(binding.etAdj.text.toString().isNotEmpty()){
Adj = (binding.etAdj.text.toString()).toFloat()
}
if(binding.etOpp.text.toString().isNotEmpty()){
Opp = (binding.etOpp.text.toString()).toFloat()
}
if(binding.etAngle.text.toString().isNotEmpty()){
Angle = (binding.etAngle.text.toString()).toFloat()
}
}
private fun countSelected() {
binding.cbHyp.setOnCheckedChangeListener { compoundButton, b ->
if(binding.cbHyp.isChecked){
numberCB++
}
else{
numberCB--
}
}
binding.cbAdj.setOnCheckedChangeListener { compoundButton, b ->
if(binding.cbAdj.isChecked){
numberCB++
}
else{
numberCB--
}
}
binding.cbOpp.setOnCheckedChangeListener { compoundButton, b ->
if(binding.cbOpp.isChecked){
numberCB++
}
else{
numberCB--
}
}
binding.cbAngle.setOnCheckedChangeListener { compoundButton, b ->
if(binding.cbAngle.isChecked){
numberCB++
}
else{
numberCB--
}
}
}
这个怎么样?逻辑是一样的。它只是在语法上进行了简化。
private fun validateNumbers() = with(binding) {
if (etHip.text.toString().isNotEmpty()) Hip = (etHip.text.toString()).toFloat()
if (etAdj.text.toString().isNotEmpty()) Adj = (etAdj.text.toString()).toFloat()
if (etOpp.text.toString().isNotEmpty()) Opp = (etOpp.text.toString()).toFloat()
if (etAngle.text.toString().isNotEmpty()) Angle = (etAngle.text.toString()).toFloat()
}
private fun countSelected() = with(binding) {
setOf(cbHyp, cbAdj, cbOpp, cbAngle).forEach {
it.setOnCheckedChangeListener { if (it.isChecked) numberCB++ else numberCB-- }
}
}
对于这两个函数,您可以将它们包装在 with(binding)
中,这样您就不必一直写 binding.
对于 validateNumbers
,您可以使用 toFloatOrNull()
将值转换为 Float,或者如果它不作为 Float 求值则为 null(例如空字符串无效)。然后您可以使用 Elvis 运算符 ?:
来提供默认值。所以如果你不想改变这个值,它可以 return 本身。
此外,由于您重复执行此操作,因此您可以创建一个从 EditText 获取值的快捷方式。这是TextView的一种,所以你可以把它写成TextView的扩展。
private fun TextView.toFloatOrNull() = text.toString().toFloatOrNull()
private fun validateNumbers() = with(binding) {
Hip = etHip.toFloatOrNull() ?: Hip
Adj = etAdj.toFloatOrNull() ?: Adj
Opp = etOpp.toFloatOrNull() ?: Opp
Angle = etAngle.toFloatOrNull() ?: Angle
}
使用 countSelected()
因为他们都在他们的听众中做完全相同的事情,所以你可以给他们所有相同的听众。 lambda 中的第二个参数是它是否刚刚被检查,所以你也可以稍微简化一下逻辑。您可以使用 listOf(...).forEach
来获取它们。
fun countSelected() = with(binding) {
val listener = OnCheckedChangeListener { _ isChecked ->
if (isChecked) numberCB++ else numberCB--
}
listOf(cbHyp, cbAdj, cbOpp, cpAngle).forEach {
it.onCheckedChangeListener = listener
}
}
我还会将函数名称更改为更具描述性的名称。您的函数不计算某些东西...它正在设置复选框来计算它们自己。
注意,属性 和变量名按照惯例应以小写字母开头。这将使您的代码更易于阅读。大写首字母通常保留用于 class 和接口名称。 (它们也用于其他一些语言中的函数名称,但您不应该在 Kotlin 中这样做,否则它们会与构造函数调用混淆。)