Declare a class with a non-default constructor or attribute

In Java, a class can have one or more constructors. Kotlin does the same, but with a twist, by distinguishing between primary constructors (usually the primary and concise method that initializes a class and is declared outside the class body) and secondary/secondary constructors (declared inside the class body). It is also possible to add additional initialization logic to the initialization statement block

Initialization class: main constructor and initialization statement block

We saw in the Kotlin foundation how do you declare a class



In general, all declarations of a class are in curly braces,The bracketed block is called the main constructor. It serves two purposes

1. Indicate the constructor parameters

2. Define the properties to be initialized with these parameters
.

The most explicit code you can write to accomplish the same thing



constructorThe keyword is used to start a declaration of a master constructor or slave constructor

The init keyword is used to introduce an initialization statement block that contains the code executed when the class is created and is used with the main constructor. Initialization code cannot be included because the main constructor has syntactic limitations. You can also declare multiple blocks of initialization statements in a class

There is no need to put the initialization code in the initialization block in this example because it can be combined with the declaration of the name attribute. If the main constructor does not have annotations or visibility modifiers, you can also remove the constructor keyword



The code can be simplified by prefixing the parameter with the val keyword, which replaces the attribute definition in the class



Val means that the corresponding property is initialized with the constructor’s parameters

You can declare a default value for a constructor parameter just like a function parameter



To create an instance of a class, you simply call the constructor directly, without the new keyword



Attention! If all constructor arguments have default values, the compiler generates an additional constructor with no arguments to use all the default values

If your class has a parent class, the main constructor also initializes the parent class. You can do this by providing the parent constructor parameter in the parent reference of the base class list

If no constructor is declared for a class, a default constructor is generated that does nothing

If you inherit from the User class and do not provide any constructors, you must explicitly call the parent class’s constructor, even if it has no arguments



That’s why you need an empty parenthesis after the parent class name, right. Note the difference with interfaces:The interface has no constructor, so you don’t need parentheses after its name in the parent class list

To ensure that your class is not instantiated by other code, you must mark the constructor private



Because it has only one private constructor, code outside the class cannot instantiate it

An alternative to the private constructor

In Java, the class is either a container of static utility members or a singleton by using the private constructor to disallow instantiation of the class. Top-level functions can be used in Kotlin to identify static utilities. To represent singletons, you can use object declarations.

Constructor: Initialize the parent class in different ways

Most scenarios that require overloaded constructors in Java are covered by Kotlin’s syntax for supporting parameter defaults and parameter naming. Tip: Do not declare multiple slave constructors to overload and provide parameter defaults. Instead, specify default values

But there are still situations where multiple constructors are needed. Imagine a View class declared in Java with two constructors. The similar declaration in Kotlin is as follows

This class does not declare a primary constructor, but does declare two slave constructors, which are used by the slave constructorconstructorKeyword extraction. Any number of slave constructors can be declared

To extend the class, declare the same constructor

You can also use the this keyword to call another constructor of your own class from one constructor

If the class has no primary constructor, then each slave constructor must either initialize the base class or delegate to another constructor that does so

Implements properties declared in the interface

In Kotlin, interfaces can contain abstract property declarations



This means that the class implementing the User interface needs to provide a way to get the name value. The interface itself does not contain any state, so only the class that implements the interface will store the value if needed.



For privateUser, declare this property directly in the main constructor, which implements the abstract property from User, so mark it as Override. For subscribeingUser, the Name attribute is implemented through a custom getter that has no supporting field to store its value and only a getter that gets a nickname from the email each time it is called. For FacebookUser, Associate name with a value at initialization, which can be obtained by ID

In addition to abstract declarations, interfaces can also contain properties with getters and setters, as long as they do not reference a support field (which requires storing state in the interface, which is not allowed)



The property has no supported fields at this point, and the resulting value is computed on each access. The name property has a custom getter that can be inherited, whereas email must be overridden. Properties implemented in a class have full access to the supported fields

Access support fields through getters or setters

Combine a property that stores a value with a property that has a custom accessor that evaluates the value on each access to implement a property that stores the value and provides additional logic when the value is accessed and modified. To support this, you need to be able to access the property’s supporting fields from its accessor

use



You can change the value of an attribute as usual using user.address=”new Value “, which calls the setter underneath. Here the setter is redefined, so the output log is printed

The special identifier field is used in the function body of the setter to access the value of the supported field, only the value can be read in the getter, and both can be read and written in the setter

If you explicitly reference or use the default accessor implementation, the compiler will generate support fields for the property. If you provide a custom accessor implementation that does not use field (getter if the property is of type Val, or two accessors if the property is mutable), the support field will not be rendered

Modify the visibility of the accessor

The default implementation of the accessor does not need to be changed, but when it does, the visibility of the accessor defaults to that of the property, but can be changed if necessary by placing visibility modifiers before the GET and SET keywords



This class is used to calculate the total length of words added together. The property that holds the total length is public because it is part of the API that the class provides to the user. But make sure it can only be modified in the class, otherwise external code might modify it and store an incorrect value. So you have the compiler generate a getter for default visibility and a private setter

Methods generated by the compiler: data classes and class delegates

Generic object method

1. String representation: toString()

Kotlin also provides a way to get the string representation of a class object. By default, the string representation of an object is of the form Client@5e9f23b4. This is not very useful and needs to be overridden

2. Object equality: equals()

All computation on the Client class takes place outside of it, and this class is only used to store data. However, there are occasional requirements for this class behavior, such as wanting to treat objects that contain the same data as equal

The IS check is a Java emulation of instanceof to check whether a value is of a specified type

== denotes equality

In Java, you can use == to compare base data types to reference types, values if applied to base data types and references if applied to reference types

In Kotlin == is the default way to compare two objects, essentially calling equals to compare two values. If equals is overridden in your class, it is safe to compare instances with ==. To do a reference comparison, use the === operator

3.Hash container: hashCode()

The hashCode method is usually overridden along with equals

When no overriding

The reason is that the Client class lacks a hashCode method, so it violates the general hashCode contract: if two objects are equal, they must have the same hash value. Values in a hashset are compared in an optimized way: first their hash value is compared, then the real value is compared only if they are equal. In the previous example, two different instances have different hash values, so set considers it to contain no second object, even though equal returns true, so a Hashset will not work on such an object if the rules are not followed

Fixed problem

It works as expected in all situations

Data classes: Implementations that automatically generate common methods

If you want your tear to be a convenient data container and you want to override toString and other three methods, you don’t have to generate those methods in Kotlin. You can simply add data modifiers to the class



We now have a class that overrides all the standard Java methods

Equals is used to compare instances

HashCode is used as a key for hash-based containers such as HashMap

ToStirng is used to generate a string representation of all the fields of the class in declarative order

The equals and hashCode methods take into account all properties declared in the main constructor. Generated equals checks whether the values of all attributes are equal. HashCode returns a hash value generated based on all attributes

Data classes and immutability: The copy() method although var can also be used for data class attributes, it is highly recommended to use only read-only attributes to make instances of data classes immutable. This is required if you want to use such instances as keys. To make it easier to work with immutable objects’ data, the compiler generates one more method for them: a method that allows you to copy instances of the class and modify the values of some properties while copying. Creating a copy, which has a separate life and does not affect where the original instance is referenced in the code, is usually a good choice for modifying an instance.

Manually implement copy()

Tests and Results

Class delegate: usebyThe keyword

When you extend a class and rewrite some methods, the code becomes dependent on the implementation details of the inherited class. As the system evolves and the implementation of the base class is modified or new methods are added to the system, your assumptions about the behavior of the class become invalid and the code may end up behaving incorrectly.

Kotlin addresses these issues by treating classes as final by default, which ensures that only classes that are designed to be extensible can be inherited. When using such a class, you will see that it is open, and care will be taken to make these changes compatible with derived classes. But we often need to add some behavior to another class, even if it’s not designed to be extensible. A common implementation is the decorator pattern. The essence of this pattern is to create a new class that implements the same interface as the original class and stores the instance of the original class as a field. Methods that have the same behavior as the original class don’t need to be modified, they just need to be forwarded directly to an instance of the original class, but that requires quite a bit of boilerplate code.

When kotlin implements an interface, can he delegate the implementation of that interface to another object using the by keyword

Before the by keyword is used

After the by keyword is used



All of the method implementations in the class are gone, the compiler generates them, and the implementation is similar to what it was before, so there’s no need to write code by hand when the compiler can do the same thing for you. You can override methods when you want to change their behavior

objectKeywords: combine declaring a class with creating an instance

The object keyword appears in a variety of situations 1. Object declarations are a way to define singletons 2. Associated objects can hold factory methods and other methods related to the class but not dependent on the class instance when invoked, and their members can be accessed by class name 3. Object expressions are used to replace Java’s anonymous inner classes

Object declaration: Create a singleton

Singleton pattern: Defines a method that uses the Provate constructor and uses static fields to hold only instances of the class kotlin is combined with the singleton declaration of the class through object life

Declare an organization’s payroll using an object



Object declarations are introduced through the object keyword, and an object declaration can be very efficientDefine a class and its variables in one sentence.

Like classes, an object declaration can contain declarations for attributes, methods, initialization blocks, and so on. The only thing not allowed is constructors (including master-slave constructors)

Unlike normal class instances, object declarations are created immediately when they are defined, and constructors do not need to be called elsewhere in the code, so it makes no sense to define a constructor for them

Like variables, object declarations allow you to use object addition. Character to call methods and access properties

Object declarations can also inherit from classes and interfaces, which is often useful if your framework needs to implement an interface, but your implementation doesn’t contain any state

Singletons and dependency injection

In large-scale software system using the object statement is not always ideal, they are dependent on a small number of only a few or no depend on in the code to use, but in with other parts in the system has a very large component is not much interaction, of object instantiation because you have no control, and can’t specify certain parameters by constructing method. This means that you can’t replace the implementation of the object itself, or other classes that the object depends on, in a different configuration of the unit test or software system. If you need that capability, you need a dependency injection framework like Guice

It is also possible to declare objects in classes that, again, have a single instance: they do not have distinct instances in each container class instance, such as placing a comparator in the class to compare specific objects

Use Kotlin objects in Java

The Kotlin object declaration is compiled into a class that holds its single INSTANCE through a static field, always named INSTANCE. To visit kotlin from Java object can access the INSTANCE of a static field: Comparator.INSTANCE.com pare said (x1, x2); The field type is Comparator

Companion objects: factory methods and static member sites

Kotlin classes cannot have static members. Instead, Kotlin relies on package-level functions (which replace Java’s static methods in most cases) and object declarations (which replace Java’s static methods in other cases, including static fields). Top-level functions are recommended in most cases, but they cannot access the private members of a class. If you need to write a function that can be called without an instance of the class but needs to access the inside of the class, write it as a declared member of the object in that class. An example of such a function is the factory method

An object defined in a class can be tagged with the Companion keyword, which gives you the ability to access the object’s methods and properties directly through the container class name, without explicitly specifying the object name, resulting in a syntax similar to Java static method calls



The companion object is a good place to call the private constructor, and it has access to all the private members of the class, including the private constructor, which is ideal for implementing the factory pattern.

example

Use factory methods instead of constructors



This can be called by class namecompanion objectThe method of



Here the factory method can return a subclass of the class that declared the method, just like the two subclasses in the example.You can also avoid creating new objects when you don’t need themYou can ensure that each email corresponds to a unique User instance, and that if the email already exists in the cache, the factory method will return the existing instance instead of creating a new one. If you need to extend such a class, it may be better to use multiple constructors because the associated object members cannot be overridden in a subclass

An accompanying object used as a normal object

An associated object is a common object that lives in a class, can have a name, and implements an interface or extension function or property

Declare a named companion object

In most cases, the associated object is referred to by the name of the class that contains it, so you don’t have to worry about its name and can specify it if necessary as shown in the figure above. If the name is omitted, the default assignment is Companion

Implement the interface in the companion object

You can simply use the name of the containing class as an object instance that implements the interface. Suppose you have many types of objects on your system, including Person, and you want to provide a common way to create all types of objects. Suppose you have a JSONFactory interface that deserializes objects from JSON, and all objects in your system are created through this factory, you can provide such an interface implementation for the Person class



At this point, if you have a function that uses abstract methods to load entities, you can pass it a Person object.

Associated object extension

What if you need to define methods that can be called by the class itself, like companion object methods or Java static methods? If the class has a companion object, you can do this by defining extension functions on it. If class C has an associated object and an extension function func is defined on c.panion, it can be called with c.func ().

Define an extension function for the associated object

In order to be able to define an extension for your class, you must declare a companion object in it, even if it is empty

Object expressions: Anonymous inner classes written differently

The object keyword can be used to declare not only singletons but also anonymous objects.

Implement event listeners using anonymous objects



The syntax is the same as the object declaration, except that the object name is removed. An object expression declares a class and creates an instance of that class, but does not assign a name to the object

If you need to assign a name, you can store it in a variable



Kotlin’s anonymous object can implement multiple interfaces or none, and it is not singleton; a new object instance is created each time an object expression is executed. Code in an object expression can access variables in the function that created it, and is not limited to final variables, and can change the value of variables in an object expression

Access local variables from anonymous objects



Object expressions are most useful when you need to override multiple methods in anonymous objects