Hello Readers, CoolMonkTechie heartily welcomes you in this article (5 Quick Valuable Concepts To Learn Kotlin Programming Language).
In this article, We will learn about Valuable Concepts To Learn Kotlin Programming Language. At Google I/O 2019, Google announced that Android development will be increasingly Kotlin-first, and we’ve stood by that commitment. Kotlin is an expressive and concise programming language that reduces common code errors and easily integrates into existing apps. If we’re looking to build an Android app, we recommend starting with Kotlin to take advantage of its best-in-class features. This article shows the kotlin fundamental for android application development
For understanding the basic fundamental concepts of kotlin, we will explore the below topics one by one:
- Variable declaration
- Conditionals
- Functions
- Classes
- Interoperability
A famous quote about learning is :
” Develop a passion for learning. If you do, you will never cease to grow.”
So Let’s begin.
1. Variable declaration
Kotlin uses two different keywords to declare variables: val
and var
.
- Use
val
for a variable whose value never changes. We can’t reassign a value to a variable that was declared usingval
. - Use
var
for a variable whose value can change.
In the example below, count
is a variable of type Int
that is assigned an initial value of 10
:
var count: Int = 10
Int
is a type that represents an integer, one of the many numerical types that can be represented in Kotlin. Similar to other languages, we can also use Byte
, Short
, Long
, Float
, and Double
depending on our numerical data.
The var
keyword means that we can reassign values to count
as needed. For example, we can change the value of count
from 10
to 15
:
var count: Int = 10
count = 15
Some values are not meant to be changed, though. Consider a String
called languageName
. If we want to ensure that languageName
always holds a value of “Kotlin”, then we can declare languageName
using the val
keyword:
val languageName: String = "Kotlin"
These keywords allow us to be explicit about what can be changed. Use them to our advantage as needed. If a variable reference must be reassignable, then declare it as a var
. Otherwise, use val
.
Type inference
Continuing the previous example, when we assign an initial value to languageName
, the Kotlin compiler can infer the type based off of the type of the assigned value.
Since the value of "Kotlin"
is of type String
, the compiler infers that languageName
is also a String
. Note that Kotlin is a statically-typed language. This means that the type is resolved at compile time and never changes.
In the following example, languageName
is inferred as a String
, so we can’t call any functions that aren’t part of the String
class:
val languageName = "Kotlin"
val upperCaseName = languageName.toUpperCase()
// Fails to compile
languageName.inc()
toUpperCase()
is a function that can only be called on variables of type String
. Because the Kotlin compiler has inferred languageName
as a String
, we can safely call toUpperCase()
. inc()
, however, is an Int
operator function, so it can’t be called on a String
. Kotlin’s approach to type inference gives us both conciseness and type-safety.
Null safety
In some languages, a reference type variable can be declared without providing an initial explicit value. In these cases, the variables usually contain a null value. Kotlin variables can’t hold null values by default. This means that the following snippet is invalid:
// Fails to compile
val languageName: String = null
For a variable to hold a null value, it must be of a nullable type. We can specify a variable as being nullable by suffixing its type with ?
, as shown in the following example:
val languageName: String? = null
With a String?
type, we can assign either a String
value or null
to languageName
.
We must handle nullable variables carefully or risk a dreaded NullPointerException
. In Java, for example, if we attempt to invoke a method on a null value, our program crashes.
Kotlin provides a number of mechanisms for safely working with nullable variables.
2. Conditionals
Kotlin features several mechanisms for implementing conditional logic. The most common of these is an if-else statement. If an expression wrapped in parentheses next to an if
keyword evaluates to true
, then code within that branch (i.e. the immediately-following code that is wrapped in curly braces) is executed. Otherwise, the code within the else
branch is executed.
Example : if / else
if (count == 42) {
println("I have the answer.")
} else {
println("The answer eludes me.")
}
We can represent multiple conditions using else if
. This lets us represent more granular, complex logic within a single conditional statement, as shown in the following example:
if (count == 42) {
println("I have the answer.")
} else if (count > 35) {
println("The answer is close.")
} else {
println("The answer eludes me.")
}
Conditional Expressions
Conditional statements are useful for representing stateful logic, but we may find that we repeat ourself when writing them. In the example above, we simply print a String
in each branch. To avoid this repetition, Kotlin offers conditional expressions. The last example can be rewritten as follows:
val answerString: String = if (count == 42) {
"I have the answer."
} else if (count > 35) {
"The answer is close."
} else {
"The answer eludes me."
}
println(answerString)
Implicitly, each conditional branch returns the result of the expression on its final line, so we don’t need to use a return
keyword. Because the result of all three branches is of type String
, the result of the if-else expression is also of type String
. In this example, answerString
is assigned an initial value from the result of the if-else expression. Type inference can be used to omit the explicit type declaration for answerString
, but it’s often a good idea to include it for clarity.
We aware that Kotlin does not include a traditional ternary operator, instead favoring the use of conditional expressions.
As the complexity of our conditional statement grows, we might consider replacing our if-else expression with a when expression, as shown in the following example:
val answerString = when {
count == 42 -> "I have the answer."
count > 35 -> "The answer is close."
else -> "The answer eludes me."
}
println(answerString)
Each branch in a when
expression is represented by a condition, an arrow (->
), and a result. If the condition on the left-hand side of the arrow evaluates to true, then the result of the expression on the right-hand side is returned. Note that execution does not fall through from one branch to the next. The code in the when
expression example is functionally-equivalent to that in the previous example but is arguably easier to read.
Smart Casting
Kotlin’s conditionals highlight one of its more powerful features, smart casting. Rather than using the safe-call operator or the not-null assertion operator to work with nullable values, we can instead check if a variable contains a reference to a null value using a conditional statement, as shown in the following example:
val languageName: String? = null
if (languageName != null) {
// No need to write languageName?.toUpperCase()
println(languageName.toUpperCase())
}
Within the conditional branch, languageName
may be treated as non-nullable. Kotlin is smart enough to recognize that the condition for executing the branch is that languageName
does not hold a null value, so we do not have to treat languageName
as nullable within that branch. This smart casting works for null checks, type checks, or any condition that satisfies a contract.
3. Functions
We can group one or more expressions into a function. Rather than repeating the same series of expressions each time that we need a result, we can wrap the expressions in a function and call that function instead.
To declare a function, use the fun
keyword followed by the function name. Next, define the types of inputs that our function takes, if any, and declare the type of output that it returns. A function’s body is where we define expressions that are called when our function is invoked.
Building on previous examples, here’s a complete Kotlin function:
fun generateAnswerString(): String {
val answerString = if (count == 42) {
"I have the answer."
} else {
"The answer eludes me"
}
return answerString
}
The function in the example above has the name generateAnswerString
. It doesn’t take any input. It outputs a result of type String
. To call a function, use its name, followed by the invocation operator (()
). In the example below, the answerString
variable is initialized with the result from generateAnswerString()
.
val answerString = generateAnswerString()
Functions can take arguments as input, as shown in the following example:
fun generateAnswerString(countThreshold: Int): String {
val answerString = if (count > countThreshold) {
"I have the answer."
} else {
"The answer eludes me."
}
return answerString
}
When declaring a function, we can specify any number of arguments and their types. In the example above, generateAnswerString()
takes one argument named countThreshold
of type Int
. Within the function, we can refer to the argument by using its name.
When calling this function, we must include an argument within the function call’s parentheses:
val answerString = generateAnswerString(42)
Simplifying function declarations
generateAnswerString()
is a fairly simple function. The function declares a variable and then immediately returns. When the result of a single expression is returned from a function, we can skip declaring a local variable by directly returning the result of the if-else expression contained in the function, as shown in the following example:
fun generateAnswerString(countThreshold: Int): String {
return if (count > countThreshold) {
"I have the answer."
} else {
"The answer eludes me."
}
}
We can also replace the return keyword with the assignment operator:
fun generateAnswerString(countThreshold: Int): String = if (count > countThreshold) {
"I have the answer"
} else {
"The answer eludes me"
}
Anonymous functions
Not every function needs a name. Some functions are more directly identified by their inputs and outputs. These functions are called anonymous functions. We can keep a reference to an anonymous function, using this reference to call the anonymous function later. We can also pass the reference around our application, as with other reference types.
val stringLengthFunc: (String) -> Int = { input ->
input.length
}
Like named functions, anonymous functions can contain any number of expressions. The returned value of the function is the result of the final expression.
In the example above, stringLengthFunc
contains a reference to an anonymous function that takes a String
as input and returns the length of the input String
as output of type Int
. For that reason, the function’s type is denoted as (String) -> Int
. This code does not invoke the function, however. To retrieve the result of the function, we must invoke it with like we would a named function. We must supply a String
when calling stringLengthFunc
, as shown in the following example:
val stringLengthFunc: (String) -> Int = { input ->
input.length
}
val stringLength: Int = stringLengthFunc("Android")
Higher-order functions
A function can take another function as an argument. Functions that use other functions as arguments are called Higher-order functions. This pattern is useful for communicating between components in the same way that we might use a callback interface in Java.
Here’s an example of a higher-order function:
fun stringMapper(str: String, mapper: (String) -> Int): Int {
// Invoke function
return mapper(str)
}
The stringMapper()
function takes a String
along with a function that derives an Int
value from a String
that we pass into it.
We can call stringMapper()
by passing a String
and a function that satisfies the other input parameter, namely a function that takes a String
as input and outputs an Int
, as shown in the following example:
stringMapper("Android", { input ->
input.length
})
If the anonymous function is the last parameter defined on a function, we can pass it outside of the parentheses used to invoke the function, as shown in the following example:
stringMapper("Android") { input ->
input.length
}
Anonymous functions can be found throughout the Kotlin standard library.
4. Classes
All of the types mentioned so far are built into the Kotlin programming language. If we would like to add our own custom type, we can define a class using the class
keyword, as shown in the following example:
class Car
Properties
Classes represent state using properties. A property is a class-level variable that can include a getter, a setter, and a backing field.
Since a car needs wheels to drive, we can add a list of Wheel
objects as a property of Car
, as shown in the following example:
class Car {
val wheels = listOf<Wheel>()
}
Note that wheels
is a public val
, meaning that wheels
can be accessed from outside of the Car
class, and it can’t be reassigned. If we want to obtain an instance of Car
, we must first call its constructor. From there, we can access any of its accessible properties.
val car = Car() // construct a Car
val wheels = car.wheels // retrieve the wheels value from the Car
If we want to customize our wheels, we can define a custom constructor that specifies how our class properties are initialized:
class Car(val wheels: List<Wheel>)
In the example above, the class constructor takes a List<Wheel>
as a constructor argument and uses that argument to initialize its wheels
property.
Class functions and encapsulation
Classes use functions to model behavior. Functions can modify state, helping us to expose only the data that we wish to expose. This access control is part of a larger object-oriented concept known as encapsulation.
In the following example, the doorLock
property is kept private from anything outside of the Car
class. To unlock the car, we must call the unlockDoor()
function passing in a valid key, as shown in the following example:
class Car(val wheels: List<Wheel>) {
private val doorLock: DoorLock = ...
fun unlockDoor(key: Key): Boolean {
// Return true if key is valid for door lock, false otherwise
}
}
If we would like to customize how a property is referenced, we can provide a custom getter and setter. For example, if we would like to expose a property’s getter while restricting access to its setter, we can designate that setter as private
:
class Car(val wheels: List<Wheel>) {
private val doorLock: DoorLock = ...
var gallonsOfFuelInTank: Int = 15
private set
fun unlockDoor(key: Key): Boolean {
// Return true if key is valid for door lock, false otherwise
}
}
With a combination of properties and functions, we can create classes that model all types of objects.
5. Interoperability
One of Kotlin’s most important features is its fluid interoperability with Java. Because Kotlin code compiles down to JVM bytecode, our Kotlin code can call directly into Java code and vice-versa. This means that we can leverage existing Java libraries directly from Kotlin. Furthermore, the majority of Android APIs are written in Java, and we can call them directly from Kotlin.
That’s all about in this article.
Conclusion
In this article, We understood about Valuable Concepts To Learn Kotlin Programming Language. Kotlin is a flexible, pragmatic language with growing support and momentum. We discussed about Kotlin fundamental like variable declaration, function, conditions and classes concepts which is widely used by Android developers everywhere for application development. This article showed the basic Kotlin fundamental concepts for android application development
Thanks for reading ! I hope you enjoyed and learned about the basic fundamental concepts of Kotlin for android development. Reading is one thing, but the only way to master it is to do it yourself.
Please follow and subscribe to the blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.
You can find Other articles of CoolMonkTechie as below link :
You can also follow official website and tutorials of Android as below links :
If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.
Thanks again Reading. HAPPY READING !!???