YouTip LogoYouTip

Kotlin Class Object

## Class Definition\n\nKotlin classes can contain: constructors and initialization blocks, functions, properties, inner classes, and object declarations.\n\nIn Kotlin, classes are declared using the `class` keyword, followed by the class name:\n\n```kotlin\nclass Tutorial { // Class name is Tutorial\n // The class body is enclosed in curly braces\n}\n\nWe can also define an empty class:\n\n```kotlin\nclass Empty\n\nMember functions can be defined within a class:\n\n```kotlin\nclass Tutorial() {\n fun foo() {\n print("Foo")\n } // Member function\n}\n\n* * *\n\n## Class Properties\n\n### Property Definition\n\nClass properties can be declared as mutable using the `var` keyword, or as immutable (read-only) using the `val` keyword.\n\n```kotlin\nclass Tutorial {\n var name: String = ……\n var url: String = ……\n var city: String = ……\n}\n\nWe can create class instances using the constructor just like regular functions:\n\n```kotlin\nval site = Tutorial() // There is no `new` keyword in Kotlin\n\nTo use a property, simply reference it by name:\n\n```kotlin\nsite.name // Use the dot operator to reference\nsite.url\n\nA Kotlin class can have a primary constructor and one or more secondary constructors. The primary constructor is part of the class header, located after the class name:\n\n```kotlin\nclass Person constructor(firstName: String) {\n}\n\nIf the primary constructor has no annotations and no visibility modifiers, the `constructor` keyword can be omitted.\n\n```kotlin\nclass Person(firstName: String) {\n}\n\n### Getters and Setters\n\nThe full syntax for property declaration is:\n\n```kotlin\nvar [: ] [] []\n\nBoth getters and setters are optional.\n\nIf the property type can be inferred from the initializer statement or the class's member functions, the type can be omitted. `val` properties cannot have a setter because they are read-only.\n\n```kotlin\nvar allByDefault: Int? // Error: requires an initializer, getter and setter are implemented by default\nvar initialized = 1 // Type is Int, getter and setter are implemented by default\nval simple: Int? // Type is Int, getter is implemented by default, but must be initialized in the constructor\nval inferredType = 1 // Type is Int, getter is implemented by default\n\n### Example\n\nThe following example defines a `Person` class with two mutable variables, `lastName` and `no`. `lastName` modifies the getter method, and `no` modifies the setter method.\n\n```kotlin\nclass Person {\n var lastName: String = "zhang"\n get() = field.toUpperCase() // Convert the variable to uppercase after assignment\n set\n var no: Int = 100\n get() = field // Backing field\n set(value) {\n if (value < 10) { // If the passed value is less than 10, return it\n field = value\n } else {\n field = -1 // If the passed value is greater than or equal to 10, return -1\n }\n }\n var heiht: Float = 145.4f\n private set\n}\n\n// Test\nfun main(args: Array) {\n var person: Person = Person()\n person.lastName = "wang"\n println("lastName:${person.lastName}")\n person.no = 9\n println("no:${person.no}")\n person.no = 20\n println("no:${person.no}")\n}\n\nThe output is:\n\nlastName:WANG\nno:9\nno:-1\n\nKotlin classes cannot have fields. However, sometimes a backing field is necessary when using custom accessors. For this, Kotlin provides an automatic backing field, which can be accessed using the `field` identifier.\n\nA Backing Field is a concept in Kotlin. It is an automatically generated field used to store the value of a property. It can only be used inside accessors (getter or setter) and exists only when at least one accessor's default implementation is used, or a custom accessor references it via the `field` identifier. This means that when a property requires a backing field, Kotlin provides it automatically. You can reference the backing field in accessors using the `field` identifier.\n\n```kotlin\nvar no: Int = 100\n get() = field // Backing field\n set(value) {\n if (value < 10) { // If the passed value is less than 10, return it\n field = value\n } else {\n field = -1 // If the passed value is greater than or equal to 10, return -1\n }\n }\n\nHere is an example of a backing field:\n\n```kotlin\nclass Person {\n var name: String = "initial value"\n set(value) {\n if (value.isNotEmpty()) {\n field = value\n }\n }\n}\n\nIn this example, the `name` property has a custom setter that checks if the passed value is not empty. If it is not empty, the value is assigned to the backing field using the `field` identifier. This way, when we try to assign an empty string to the `name` property, its value does not change.\n\n```kotlin\nval person = Person()\nprintln(person.name) // Outputs "initial value"\nperson.name = ""\nprintln(person.name) // Still outputs "initial value"\nperson.name = "John"\nprintln(person.name) // Outputs "John"\n\nIn the code above, we create an instance of the `Person` class and try to change the value of its `name` property. When we try to assign an empty string to it, due to the custom setter's check, the value of the `name` property remains unchanged. When we assign a non-empty string to it, its value is successfully changed to the new value.\n\nNon-null properties must be initialized at the time of definition. Kotlin provides a way to delay initialization using the `lateinit` keyword to describe a property:\n\n```kotlin\npublic class MyTest {\n lateinit var subject: TestSubject\n\n @SetUp\n fun setup() {\n subject = TestSubject()\n }\n\n @Test\n fun test() {\n subject.method() // dereference directly\n }\n}\n\n* * *\n\n## Primary Constructor\n\nThe primary constructor cannot contain any code. Initialization code can be placed in initialization blocks, which are prefixed with the `init` keyword.\n\n```kotlin\nclass Person constructor(firstName: String) {\n init {\n println("FirstName is $firstName")\n }\n}\n\nNote: The parameters of the primary constructor can be used in initialization blocks and also in property initializers defined in the class body. A concise syntax allows defining and initializing properties (which can be `var` or `val`) via the primary constructor:\n\n```kotlin\nclass People(val firstName: String, val lastName: String) {\n //...\n}\n\nIf the constructor has annotations or visibility modifiers, the `constructor` keyword is required, and the annotations and modifiers must precede it.\n\n### Example\n\nCreate a `Tutorial` class and pass the website name through the constructor:\n\n```kotlin\nclass Tutorial constructor(name: String) { // Class name is Tutorial\n // The class body is enclosed in curly braces\n var url: String = "\n var country: String = "CN"\n var siteName = name\n init {\n println("Initialize website name: ${name}")\n }\n fun printTest() {\n println("I am a class function")\n }\n}\n\nfun main(args: Array) {\n val tutorial = Tutorial("")\n println(tutorial.siteName)\n println(tutorial.url)\n println(tutorial.country)\n tutorial.printTest()\n}\n\nThe output is:\n\nInitialize website name: \n\nCN\nI am a class function\n\n* * *\n\n## Secondary Constructors\n\nA class can also have secondary constructors, prefixed with the `constructor` keyword:\n\n```kotlin\nclass Person {\n constructor(parent: Person) {\n parent.children.add(this)\n }\n}\n\nIf a class has a primary constructor, each secondary constructor must delegate to the primary constructor, either directly or indirectly through another secondary constructor. Delegating to another constructor in the same class uses the `this` keyword:\n\n```kotlin\nclass Person(val name: String) {\n constructor (name: String, age:Int) : this(name) {\n // initialization...\n }\n}\n\nIf a non-abstract class does not declare any constructors (primary or secondary), it will have a generated no-argument constructor. The constructor is `public`. If you don't want your class to have a public constructor, you need to declare an empty primary constructor with `private` visibility:\n\n```kotlin\nclass DontCreateMe private constructor () {}\n\n> Note: On the JVM virtual machine, if all parameters of the primary constructor have default values, the compiler will generate an additional no-argument constructor that uses the default values directly. This makes it easier to use Kotlin with libraries like Jackson or JPA that create class instances using no-argument constructors.\n> \n> ```kotlin\n> class Customer(val customerName: String = "")\n> ```\n\n### Example\n\n```kotlin\nclass Tutorial constructor(name: String) { // Class name is Tutorial\n // The class body is enclosed in curly braces\n var url: String = ""\n var country: String = "CN"\n var siteName = name\n init {\n println("Initialize website name: ${name}")\n }\n // Secondary constructor\n constructor (name: String, alexa: Int) : this(name) {\n println("Alexa Rank $alexa")\n }\n fun printTest() {\n println("I am a class function")\n }\n}\n\nfun main(args: Array) {\n val tutorial = Tutorial("", 10000)\n println(tutorial.siteName)\n println(tutorial.url)\n println(tutorial.country)\n tutorial.printTest()\n}\n\nThe output is:\n\nInitialize website name: \nAlexa Rank 10000\n\nCN\nI am a class function\n\n* * *\n\n## Abstract Classes\n\nAbstraction is one of the features of object-oriented programming. A class itself, or some of its members, can be declared as `abstract`. Abstract members do not have an implementation in the class.\n\nNote: There is no need to annotate abstract classes or abstract members with `open`.\n\n```kotlin\nopen class Base {\n open fun f() {}\n}\n\nabstract class Derived : Base() {\n override abstract fun f()\n}\n\n* * *\n\n## Nested Classes\n\nWe can nest classes within other classes. See the following example:\n\n```kotlin\nclass Outer {\n private val bar: Int = 1\n class Nested { // Nested class\n fun foo() = 2\n }\n}\n\nfun main(args: Array) {\n val demo = Outer.Nested().foo() // Calling format: OuterClass.NestedClass.nestedMethod/property\n println(demo) // == 2\n}\n\n* * *\n\n## Inner Classes\n\nInner classes are denoted by the `inner` keyword.\n\nAn inner class holds a reference to an object of the outer class, so inner classes can access members and functions of the outer class.\n\n```kotlin\nclass Outer {\n private val bar: Int = 1\n var v = "Member properties"\n /** Nested inner class **/\n inner class Inner {\n fun foo() = bar // Access outer class member\n fun innerTest() {\n var o = this@Outer // Get a reference to the outer class member\n println("Inner classes can reference members of the outer class, for example:" + o.v)\n }\n }\n}\n\nfun main(args: Array) {\n val demo = Outer().Inner().foo()\n println(demo) // 1\n val demo2 = Outer().Inner().innerTest()\n println(demo2) // Inner classes can reference members of the outer class, for example:Member properties\n}\n\nTo eliminate ambiguity when accessing `this` from an outer scope, we use `this@label`, where `@label` is a label that refers to the scope where `this` comes from.\n\n* * *\n\n## Anonymous Inner Classes\n\nAnonymous inner classes are created using object expressions:\n\n```kotlin\nclass Test {\n var v = "Member properties"\n fun setInterFace(test: TestInterFace) {\n test.test()\n }\n}\n\n/**\n * Define an interface\n */\ninterface TestInterFace {\n fun test()\n}\n\nfun main(args: Array) {\n var test = Test()\n /**\n * Use an object expression to create an interface object, i.e., an instance of an anonymous inner class.\n */\n test.setInterFace(object : TestInterFace {\n override fun test() {\n println("Object expressions create instances of anonymous inner classes")\n }\n })\n}\n\n* * *\n\n## Class Modifiers\n\nClass modifiers include `classModifier` and `accessModifier`:\n\n* `classModifier`: Class property modifiers, indicating the characteristics of the class itself.\n\n ```kotlin\n abstract // Abstract class\n final // Class cannot be inherited (default for classes)\n enum // Enum class\n open // Class can be inherited (classes are final by default)\n annotation // Annotation class\n ```\n\n* `accessModifier`: Access visibility modifiers.\n\n ```kotlin\n private // Visible only within the same file\n protected // Visible within the same file or in subclasses\n public // Visible everywhere\n internal // Visible within the same module\n ```\n\n### Example\n\n```kotlin\n// Filename: example.kt\npackage foo\n\nprivate fun foo() {} // Visible within example.kt\npublic var bar: Int = 5 // This property is visible everywhere\ninternal val baz = 6 // Visible within the same module
← Kotlin InterfaceKotlin Condition Control β†’