Define the class inheritance structure
Interfaces in Kotlin
The following figure declares an interface with a single abstract method named click, which all non-abstract classes that implement the interface must provide
Kotlin uses the colon instead of the extends and implements keywords. Like Java, a class can implement multiple interfaces but can only inherit from one class
The override modifier is mandatory in KotlinThis avoids accidental overrides caused by writing out the implementation method before adding the abstract method
Whereas an interface method can have a default implementation, and Java8 requires you to annotate such an implementation with the default keyword, kotlin has no special annotations and only needs to provide a method body
Now define a Focusable interface that also implements a showOff method
When your class implements these two interfaces, you don’t use either implementation,The compiler will ask you to provide your own implementation
Modify the MyButton class as follows
To invoke an inherited implementation, the super keyword can be used, but the syntax for selecting a particular implementation is different,In Java it is Clickable.super.showoff (), while in Kotlin it is super< Clickable>.showoff ()
Implement an interface containing a method body in Java
Kotlin1.0 was designed with Java 6 in mind and does not support default methods in interfaces, so it compiles each interface with a default method into a combination of a normal interface and a class that uses the method body as a static function.
Open, final, abstract modifiers: Final by default
In Java, you are allowed to subclass any class and override any method unless the final keyword is explicitly called. Making changes to a base class can lead to incorrect behavior by subclasses. This is known as a vulnerable base class problem, because the base class code changes no longer match the assumptions made in its subclasses. Any changes to the base class may result in behavior changes outside of the subclass.
In Java classes and methods are open by default, and in Kotlin classes and methods are final by default.
If you want to allow subclasses of a class, use the open modifier to identify the class and add the open modifier to every property and method that can be overridden
If you override a member of a base class or interface, the overridden member is also open by default,If you want to prevent a subclass of your class from overwriting your implementation, you can explicitly mark the overridden member as final
Open classes and smart transformations
The class default final makes smart conversions possible ina wide variety of scenarios. We mentioned earlier that smart conversions can only be used on variables that have not changed since type checking. For a class, this means that smart conversions can only be used on class attributes of type Val that have no custom accessors. This premise implies that the property must be final, otherwise a subclass that can override the property and define a custom accessor would break the key premise of intelligent transformation
In Kotlin, you can declare a class as abstruct, and that class cannot be instantiated. It usually contains some abstract members that are not implemented and must be overridden in subclasses. Abstract members are always open, so there is no need to use open explicitly
Class access modifier | Members of the relevant | commentary |
---|---|---|
final | Can’t be rewritten | Class members used by default |
open | Can be rewritten | Need to make it clear |
abstruct | Must be rewritten | Can only be used in abstract classes. Abstract members cannot have implementations |
override | Overrides a member of a parent class or interface | If I don’t say final. Overridden members are left open by default |
Visibility modifier: Defaults to public
Kotlin is almost identical to Java, but by default kotlin is public. A new modifier is also provided: internal (visible only inside a module), where a module is a set of Kotlin files compiled together, possibly an IDEA module, a set of files compiled using calls to Ant tasks, and so on. Kotlin also allows the use of private in top-level declarations, including classes, functions, and attributes, which are visible only in the file in which they are declared
Visibility modifier | Members of the class | The top statement |
---|---|---|
public | Visible everywhere | Visible everywhere |
internal | Visible in module | Visible in module |
protected | Visible in subclasses | There is no |
private | Seen in class | Visible in the file |
Kotlin disallowed referencing the low-visibility type TalkativeButton (internal) from the public function giveSpeech. General rule: The underlying type of a class and all classes used in the type argument list, or the signature of a function, have the same visibility as the class or function itself.
Note the difference between the protected modifier in Java and Kotlin. In Java, protected members can be accessed from the same package, but kotlin does not. In Kotlin, its members are only visible in the class and its subclasses
Note that the extension functions of the class do not have access to its private and protected members
Kotlin’s visibility modifier and Java
Kotlin’s public, protected, and private modifiers are retained when codified into Java bytecode. The only exception is private classes: this case is compiled into package private declarations.
A module usually consists of multiple packages, and different modules may contain declarations from the same package, so the internal qualifier becomes public in bytecode, which explains why it’s sometimes possible to access things from Java code that you can’t access from Kotlin
The internal member name of the class will be corrupted
In Kotlin an external class cannot see the private members of its inner/nested classes
Inner and nested classes: The default is nested classes
In Kotlin you can declare a class in another class, which is useful when encapsulating a helper class or putting some code close to where it will be used. But unlike Java, Kotlin’s nested classes cannot access instances of external classes unless you specifically ask them to.
Example declares a view that contains serializable state
So you can see that we’re trying to return a ButonState that implements the State interface, which works in Kotlin, which in Java would give an error,The ButtonState class implicitly stores a reference to its external MyButton in JavaMyButton cannot be serialized, and its reference breaks the serialization of ButtonState. To fix it, declare the ButtonState class static, and the nested class removes implicit references to the enclosing class. A nested class without explicit modifiers in Kotlin is the same as a static nested class in Java. To turn it into an inner class that holds a reference to an outer class, useinner
The modifier
Class A is declared in another class B | In Java | In the Kotlin |
---|---|---|
Nested classes (do not store references to external classes) | static class A | class A |
Inner class (stores references to external classes) | class A | inner class A |
The syntax for referring to an external class instance in Kotlin is also different from That in Java, requiring access to the Outer class from the Inner class with this@Outer
Sealed class: Defines a restricted class inheritance structure
Review the example in kotlin’s Foundation chapter
While it is convenient to handle all possible subclasses in the WHEN expression, you must provide an else branch to handle cases where no other branch matches. It’s inconvenient to always have to add a default branch, and more importantly, if you add a new subclass, the compiler won’t notice that anything has changed, and if you forget to add a new branch, you’ll get bugs.
Kotlin provides a solution for this: sealed class.
Add the sealed modifier to the parent class to set a strict limit on the subclasses that can be created. All direct subclasses must be nested within the parent class
Sealed classes cannot have subclasses outside of the class. If you handle all of the sealed subclasses in the WHEN expression, there is no need to provide a default branch. The class implied by the sealed modifier is an open class, and you no longer need to explicitly add the open modifier.
We cannot declare the sealed interface because the compiler cannot guarantee that no one can implement this interface in Java code
In kotlin1.0, sealed is quite strict, all subclasses must be nested, and subclasses cannot be created as data classes. In 1.1, these restrictions are lifted and a subclass of Sealed can be defined anywhere in the same file