- Learn Kotlin Programming(Second Edition)
- Stephen Samuel Stefan Bocutiu
- 491字
- 2021-06-24 14:13:36
Default parameters
Sometimes, it is convenient to provide default values for parameters in a function. Let's say that we want to create a thread pool. The parameter to set the number of threads could default to the number of CPU cores. This would be a sensible default, but the user might still want to use something different.
The way to achieve this in languages without default parameters is to offer overloaded versions of the same function:
fun createThreadPool(): ExecutorService { val threadCount = Runtime.getRuntime().availableProcessors() return createThreadPool(threadCount) } fun createThreadPool(threadCount: Int): ExecutorService { return Executors.newFixedThreadPool(threadCount) }
Here, the user can now choose which version to invoke. However, the number of parameters sometimes means that we end up with many overloaded variations of the same function, resulting in needless boilerplate. For example, the Java BigDecimal standard library has the following functions:
public BigDecimal divide(BigDecimal divisor) public BigDecimal divide(BigDecimal divisor, RoundingMode roundingMode) public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode)
There are many other variations. Each function just delegates to the next one with a sensible default.
In Kotlin, a function can define one or more of its parameters to have default values, which are used if the arguments are not specified. This allows a single function to be defined for several use cases, thereby avoiding the need for multiple overloaded variants.
Here is the divide function again, but this time, by using default parameters, we can reduce the definition to a single function:
fun divide(divisor: BigDecimal, scale: Int = 0, roundingMode: RoundingMode = RoundingMode.UNNECESSARY): BigDecimal
When invoking this function, we can omit some or all of the parameters, but once a parameter is omitted, all the following parameters must be omitted as well. For instance, we could invoke this function in the following ways:
divide(BigDecimal(12.34)) divide(BigDecimal(12.34), 8) divide(BigDecimal(12.34), 8, RoundingMode.HALF_DOWN)
Each of the previous examples call the same method, but where a parameter has been omitted, the default value from the function definition is inserted. In other words, the previous example is exactly the same as the following:
divide(BigDecimal(12.34), 0, RoundingMode.UNNECESSARY) divide(BigDecimal(12.34), 8, RoundingMode.UNNECESSARY) divide(BigDecimal(12.34), 8, RoundingMode.HALF_DOWN)
However, the following would not be legal:
divide(BigDecimal(12.34), RoundingMode.HALF_DOWN)
To solve this problem, we can mix named parameters and default parameters:
divide(BigDecimal(12.34), roundingMode = RoundingMode.HALF_DOWN)
In general, using named parameters in combination with default parameters is very powerful. It allows us to provide one function, and users can selectively override the defaults they wish.
Default parameters can also be used in constructors to avoid the need for multiple secondary constructors. The following example shows multiple constructors:
class Student(val name: String, val registered: Boolean, credits: Int) { constructor(name: String) : this(name, false, 0) constructor(name: String, registered: Boolean) : this(name, registered, 0) }
These constructors can be rewritten as the following:
class Student2(val name: String, val registered: Boolean = false, credits: Int = 0)
Let's now learn about extension functions.
- Getting Started with CreateJS
- 數據結構(Python語言描述)(第2版)
- Android NDK Beginner’s Guide
- Python自然語言處理(微課版)
- Securing WebLogic Server 12c
- Learning Apache Mahout Classification
- The Professional ScrumMaster’s Handbook
- Hands-On Neural Network Programming with C#
- Hadoop 2.X HDFS源碼剖析
- 零代碼實戰:企業級應用搭建與案例詳解
- Tableau Desktop可視化高級應用
- Learning Scrapy
- 嵌入式Linux與物聯網軟件開發:C語言內核深度解析
- Scratch 3少兒交互式游戲編程一本通
- Game Development with SlimDX