Specific Use of Object Expression and Object Declaration in Kotlin
- 2021-11-13 18:18:53
- OfStack
The main difference between an Kotlin object expression and an anonymous inner class in Java is that an anonymous inner class can only specify one parent type, but an object expression can specify 0 ~ N skin types.
1. Object expressions
The syntax format of the object expression is as follows:
object [: 0~N Parent type ]{
// Class body part of object expression
}
Object expressions also have the following rules:
An object expression cannot be an abstract class because the system creates an object immediately when it creates an object expression. Therefore, it is not allowed to define object expressions as abstract classes. An object expression cannot define a constructor. But object expressions can define initialization blocks that do what the constructor needs to do. Object expressions can contain inner classes, not nested classes.
package `0705`
interface Outputable {
fun output(msg: String)
}
abstract class Product(var price: Double) {
abstract val name: String
abstract fun printInfo()
}
fun main(args: Array<String>) {
// Specify 1 Object expression of parent type (interface)
var ob1 = object : Outputable {
override fun output(msg: String) {
for (i in 1..6) {
println("<h${i}>${msg}</h${i}>")
}
}
}
ob1.output(" Just output something ")
println("-----------------------------------------------")
// Object expressions that specify zero parent types
var ob2 = object {
// Initialization block
init {
println(" Initialization block ")
}
// Attribute
var name = "Kotlin"
// Method
fun test() {
println("test Method ")
}
// Can only contain inner classes, not nested classes
inner class Inner
}
println(ob2.name)
ob2.test()
println("-----------------------------------------------")
// Specifies an object expression of two parent types
var ob3 = object : Outputable, Product(1.23) {
override fun output(msg: String) {
println(" Output information: ${msg}")
}
override val name: String
get() = " Laser printer "
override fun printInfo() {
println(" High-speed aurora printers support automatic double-sided printing! ")
}
}
println(ob3.name)
ob3.output("Kotlin Learn slowly ")
ob3.printInfo()
}
Output:
< h1 > Just output something < /h1 >
< h2 > Just output something < /h2 >
< h3 > Just output something < /h3 >
< h4 > Just output something < /h4 >
< h5 > Just output something < /h5 >
< h6 > Just output something < /h6 >
-----------------------------------------------
Initialization block
Kotlin
test method
-----------------------------------------------
Laser printer
Output information: Kotlin learn slowly
High-speed aurora printers support automatic double-sided printing!
Object expressions for Kotlin can be divided into two situations:
The Kotlin compiler recognizes the true type of an object expression when it is within the local scope of a method, or when it is decorated with private. Non-private-decorated object expressions are similar to Java's anonymous inner classes in that the compiler treats the object expression only as if it were inheriting a parent class or implementing an interface. If it has no parent type, the system treats it as an Any type.
package `0705`
class ObjectExprType {
private val ob1 = object {
val name: String = "Kotlin"
}
internal val ob2 = object {
val name: String = "Kotlin"
}
private fun privateBar()=object {
val name:String="Java"
}
fun publicBar()=object {
val name:String="Java"
}
fun test(){
//ob1 Yes private Object expression, the compiler can recognize its true type
println(ob1.name)
//ob2 Right and wrong private Object expression, the compiler when it is Any Type
// println(ob2.name)
//privateBar Yes private Function, the compiler can recognize the true type of the object expression it returns
println(privateBar().name)
//publicBar Right and wrong private Function, and the compiler treats the object expression it returns as Any Type
// println(publicBar().name)
}
}
fun main(args: Array<String>) {
ObjectExprType().test()
}
Output:
Kotlin
Java
The Kotlin compiler recognizes the true type of an private object expression.
Object expressions of Kotlin can access or decorate local variables within their scope.
fun main(args: Array<String>) {
var a = 20
var obj = object {
fun change() {
println("change() Method to modify variables a Value of ")
a++
}
}
obj.change()
println(a)
}
Output:
The change () method modifies the value of the variable a
21
Kotlin's object expressions are enhanced in three ways over Java's anonymous inner classes:
Object expressions can specify multiple parent types The Kotlin compiler can more accurately identify the types of private object expressions in a local scope. Object expressions can access or modify local variables in their scope
2. Object declarations and singleton patterns
The syntax format of object declaration is as follows:
object ObjectName [: 0~N Parent type ]{
// Class body part of object expression
}
The syntax of object declarations is similar to that of object expressions, except that object expressions have no name after the object keyword; The object declaration needs to specify a name after the object keyword.
There are also the following differences between the two:
An object expression is an expression that can be assigned to a variable; The object declaration is not an expression and cannot be used for assignment. Object declarations can contain nested classes, not inner classes; Object expressions can contain inner classes, not nested classes. Object declarations cannot be defined within functions and methods; However, object expressions can be nested in other object declarations or non-inner classes.
package `0705`
interface Outputable {
fun output(msg: String)
}
abstract class Product(var price: Double) {
abstract val name: String
abstract fun printInfo()
}
// Specify 1 Object expression of parent type
object MyObject1 : Outputable {
override fun output(msg: String) {
for (i in 1..6) {
println("<h${i}>${msg}</h${i}>")
}
}
}
// Object expressions that specify zero parent types
object MyObject2 {
// Initialization block
init {
println(" Initialization block ")
}
// Attribute
var name = "Kotlin"
// Method
fun test() {
println("test Method ")
}
// Can only contain nested classes, not inner classes
class Inner
}
// Specifies an object expression of two parent types
object MyObject3 : Outputable, Product(1.23) {
override fun output(msg: String) {
println(" Output information: ${msg}")
}
override val name: String
get() = " Laser printer "
override fun printInfo() {
println(" High-speed aurora printers support automatic double-sided printing! ")
}
}
fun main(args: Array<String>) {
MyObject1.output("1 Get up and learn Kotlin")
println("-----------------------------------------------")
println(MyObject2.name)
MyObject2.test()
println("-----------------------------------------------")
println(MyObject3.name)
MyObject3.output("Kotlin That's nice ")
MyObject3.printInfo()
}
Output:
< h1 > 1 Come and learn Kotlin < /h1 >
< h2 > 1 Come and learn Kotlin < /h2 >
< h3 > 1 Come and learn Kotlin < /h3 >
< h4 > 1 Come and learn Kotlin < /h4 >
< h5 > 1 Come and learn Kotlin < /h5 >
< h6 > 1 Come and learn Kotlin < /h6 >
-----------------------------------------------
Initialization block
Kotlin
test method
-----------------------------------------------
Laser printer
Output message: Kotlin is really good
High-speed aurora printers support automatic double-sided printing!
Object declaration is specially used to implement singleton pattern. The object defined by object declaration is the only instance of this class, and the program can directly access the only instance of this class by the name of object declaration.
3. Associated objects and static members
An object declaration defined in a class can be decorated with companion, so that the object becomes a companion object.
Each class can only define one associated object at most, which is equivalent to the object of external class, and the program can directly call the members of associated objects through external class.
package `0705`
interface CompanionTest {
fun output(msg: String)
}
class MyClass {
// Use companion Modified companion object
companion object MyObject1 : CompanionTest {
val name = "name Attribute value "
override fun output(msg: String) {
for (i in 1..6) {
println("<h${i}>${msg}</h${i}>")
}
}
}
}
fun main(args: Array<String>) {
// Invoke the method of a companion object using the class in which the companion object resides
MyClass.output("Kotlin Must learn ")
println(MyClass.name)
}
Output:
< h1 > Kotlin must be learned < /h1 >
< h2 > Kotlin must be learned < /h2 >
< h3 > Kotlin must be learned < /h3 >
< h4 > Kotlin must be learned < /h4 >
< h5 > Kotlin must be learned < /h5 >
< h6 > Kotlin must be learned < /h6 >
name property value
The main function of an associated object is to simulate static members for its external class, but it is only simulation. The members of an associated object are still instance members of the associated object itself, and do not belong to the external class where the associated object is located.
4. Extension of associated objects
Companion objects can also be extended. If a class has a companion object, Kotlin allows methods and properties to be extended for the companion object.
package `0705`
interface CompanionTest {
fun output(msg: String)
}
class MyClass {
// Use companion Modified companion object
companion object : CompanionTest {
val name = "name Attribute value "
override fun output(msg: String) {
for (i in 1..6) {
println("<h${i}>${msg}</h${i}>")
}
}
}
}
// Extending methods for associated objects
fun MyClass.Companion.test() {
println(" Extended methods for associated objects ")
}
val MyClass.Companion.foo
get() = " Attributes extended for accompanying objects "
fun main(args: Array<String>) {
// Invoke the method of a companion object using the class in which the companion object resides
MyClass.output("Kotlin Must learn ")
println(MyClass.name)
// Invoke the member extended for the companion object through the class in which the companion object is located
MyClass.test()
println(MyClass.foo)
}
Output:
< h1 > Kotlin must be learned < /h1 >
< h2 > Kotlin must be learned < /h2 >
< h3 > Kotlin must be learned < /h3 >
< h4 > Kotlin must be learned < /h4 >
< h5 > Kotlin must be learned < /h5 >
< h6 > Kotlin must be learned < /h6 >
name attribute value
Extended methods for associated objects
Attributes extended for accompanying objects