类和对象
类的构造
定义
类也是用关键字class修饰。 如果是public修饰的类,public可以省略 用:表示类的继承。 继承需要在类后面加上()。 创建类实例时不需要new。 init{}表示类初始化模块。
class MainActivity : AppCompatActivity ( ) {
override fun onCreate ( savedInstanceState: Bundle? , persistentState: PersistableBundle? ) {
super . onCreate ( savedInstanceState, persistentState)
}
}
class Shape {
init {
println ( "Shape是表示形状的类" )
}
}
构造函数
主构造函数
主构造函数,放在类名后面,用constructor修饰。 没有带@符号修饰的,constructor可以省略。 主构造函数不是必须的。
class Shape1 ( name: String) {
init {
println ( "Shape1是表示形状的类,名称是 $ name " )
}
}
class Shape1 constructor ( name: String) {
}
var shape1 = Shape1 ( "通用形状" )
次构造函数
没有名称。 用关键字constructor修饰。 如果有主构造函数需要调用主构造函数。 会先调用主构造函数的初始化函数。
class Shape2 ( name: String) {
init {
println ( "Shape2是表示形状的类,名称是 $ name " )
}
constructor ( name: String, side: Int) : this ( name) {
println ( "Shape2是表示形状的类,名称是 $ name ,是 ${ side } 边形" )
}
}
var shape2 = Shape2 ( "通用形状" )
var shape3 = Shape2 ( "通用形状" , 4 )
class Shape3 {
init {
println ( "Shape3是表示形状的类" )
}
constructor ( ) {
println ( "Shape3是表示形状的类,无参" )
}
constructor ( name: String) {
println ( "Shape3是表示形状的类,名称是 $ name " )
}
constructor ( name: String, side: Int) {
println ( "Shape3是表示形状的类,名称是 $ name ,是 ${ side } 边形" )
}
}
var shape4 = Shape3 ( )
var shape5 = Shape3 ( "通用形状" )
var shape6 = Shape3 ( "通用形状" , 5 )
参数带默认值的造函数
class Shape4 {
init {
println ( "Shape4是表示形状的类" )
}
constructor ( name: String, side: Int = 6 ) {
println ( "Shape4是表示形状的类,名称是 $ name ,是 ${ side } 边形" )
}
}
var shape7 = Shape4 ( "通用形状" )
var shape8 = Shape4 ( "通用形状" , 8 )
如果要兼容Java创建实例的时候也能用默认参数,则需要加上@JvmOverloads修饰,否则编译会出错。
class Shape5 {
init {
println ( "Shape5是表示形状的类" )
}
@JvmOverloads constructor ( name: String, side: Int = 6 ) {
println ( "Shape5是表示形状的类,名称是 $ name ,是 ${ side } 边形" )
}
}
Shape5 shape4 = new Shape5 ( "通用形状" ) ;
类的成员
属性
class People ( name: String, age: Int) {
var name: String
var age: Int
init {
this . name = name
this . age = age
}
}
var people = People ( "张三" , 18 )
people. age = 19
println ( people. age )
println ( people. name )
class People1 ( var name: String, var age: Int) {
}
var people1 = People1 ( "李四" , 18 )
println ( people1. age )
println ( people1. name )
方法
class People1 ( var name: String, var age: Int) {
fun getName ( ) : String {
return name
}
fun getAge ( ) : Int {
return age
}
}
var people1 = People1 ( "李四" , 18 )
println ( people1. getName ( ) )
println ( people1. getAge ( ) )
伴生对象
使用伴生对象来模拟静态属性和方法。 伴生对象中的属性和方法可以通过类名直接访问。 用companion object进行修饰。
companion object {
var speciesCount: Int = 0
fun judgeSex ( sex: Int) : Int {
var sexName: String = when ( sex) {
0 -> "女"
1 -> "男"
else -> ""
}
return sex
}
}
People2. speciesCount
People2. judgeSex ( people2. sex)
类的继承、抽象、接口
开放修饰符
修饰符 说明 public 公共开放,默认是public internal 本模块内能访问 protected 自己和其子类 private 私有
继承
默认不能被继承。 类要能被继承需要声明open类型。 private和open不能共存。 父类中如果方法允许被重写,方法也得加上open。 用:表示继承。 方法重写需要加上override关键字。 不允许多继承即同时继承多个类。
open class People ( var name: String, var age: Int) {
protected var height: Double = 0.0
private var sex: Int = 0
open fun eat ( ) {
println ( " ${ name } 正在吃饭" )
}
protected open fun introduce ( ) {
println ( "我是个好人" )
}
fun setSex ( sex: Int) {
this . sex = sex
}
}
class Student ( name: String, age: Int) : People ( name, age) {
override fun eat ( ) {
introduce ( )
println ( "学生 ${ name } 正在吃饭" )
}
override fun introduce ( ) {
println ( "我是个好学生" )
}
}
抽象类
抽象类用关键字abstract修饰。 抽象类不一定有抽象方法,但有抽象方法的必须是抽象类。 可以有非抽象的方法。 抽象类和方法需要被实现,所以open关键字可以不写。
abstract class Shape {
abstract fun draw ( )
open fun area ( ) : Double {
throw UnsupportedOperationException ( "This method should be overridden by subclasses" )
}
}
class Circle ( val radius: Double) : Shape ( ) {
override fun draw ( ) {
println ( "画一个圆" )
}
override fun area ( ) : Double {
return Math. PI * radius * radius
}
}
class Rectangle ( val width: Double, val height: Double) : Shape ( ) {
override fun draw ( ) {
println ( "画一个长方形" )
}
override fun area ( ) : Double {
return width * height
}
}
val circle = Circle ( 10.0 )
circle. draw ( )
println ( "圆的面积是 ${ circle. area ( ) } " )
val rectangle = Rectangle ( 10.0 , 10.0 )
rectangle. draw ( )
println ( "长方形的面积是 ${ rectangle. area ( ) } " )
接口
用interface表示接口 接口不能有构造函数,否则会报错。 没实现的方法默认是抽象,所以open可以省略。 允许有实现的方法。 也是用:表示实现接口。
* 用interface 表示接口
* 1 、接口不能有构造函数,否则会报错。
* 2 、没实现的方法默认是抽象,所以open 可以省略。
* 3 、允许有实现的方法。
* * /
interface Animal {
fun eat ( )
fun makeSound ( )
fun common ( name: String) {
println ( " ${ name } 是一只可爱的动物" )
}
}
class Dog : Animal{
override fun eat ( ) {
println ( "狗正在吃饭" )
}
override fun makeSound ( ) {
println ( "狗正在汪汪叫" )
}
}
class Cat : Animal{
override fun eat ( ) {
println ( "猫正在吃饭" )
}
override fun makeSound ( ) {
println ( "猫正在喵喵叫" )
}
}
特殊类
嵌套类
在外部内定义一个类,嵌套类不能访问外部类的属性、方法等。 调用嵌套类时通过调用嵌套类时通过(外部类名称.内部类),相当是外部类的静态内部类。
class Outer ( var name: String) {
fun outFunction ( ) {
}
class NestedInObject ( var nestedName: String) {
fun nestedFunction ( ) {
}
}
}
Outer. NestedInObject ( "嵌套类" )
内部类
在类内部定义一个类,且用inner进行修饰,称为内部类。 内部类可以访问外部类的属性。 调用内部类需要先创建外部类。
class OuterInner ( var name: String) {
fun outFunction ( ) {
println ( "outFunction" )
}
inner class Inner ( var innerName: String) {
fun innerFunction ( ) {
println ( " $ innerName " )
println ( " $ name " )
outFunction ( )
}
}
}
val inner = OuterInner ( "外部类" ) . Inner ( "内部类" )
inner . innerFunction ( )
枚举类
enum class Color {
RED, GREEN, BLUE
}
val red = Color. RED
println ( red)
println ( red. name)
for ( color in Color. values ( ) ) {
println ( color)
}
enum class Planet ( val mass: Double, val radius: Double) {
MERCURY ( 3.303e+23 , 2.4397e6 ) ,
VENUS ( 4.869e+24 , 6.0518e6 ) ,
EARTH ( 5.976e+24 , 6.37814e6 ) ;
}
println ( Planet. EARTH. mass)
enum class Operation {
PLUS {
override fun apply ( x: Int, y: Int) = x + y
} ,
MINUS {
override fun apply ( x: Int, y: Int) = x - y
} ,
TIMES {
override fun apply ( x: Int, y: Int) = x * y
} ,
DIVIDE {
override fun apply ( x: Int, y: Int) : Int {
return if ( y == 0 ) throw ArithmeticException ( "Division by zero" ) else x / y
}
} ;
abstract fun apply ( x: Int, y: Int) : Int
}
Operation. PLUS. apply ( 10 , 20 )
数据类
一种用于存储数据的特殊类,其主要目的是简化数据持有者的实现。 数据类会自动为你生成一些常用的方法,比如 equals()、hashCode() 和 toString(),以及 copy() 方法(用于复制对象并修改其部分属性)。 用data修饰,需要有主构造函数。
data class Person ( val name: String, val age: Int)
val person = Person ( "张三" , 19 )
val copy = person. copy ( )
person. equals ( copy)
person. toString ( )
密封类
一种用于表示受限的类继承结构的特殊类。 密封类可以有一个或多个子类,但所有这些子类必须在同一个文件中声明。 这意味着你不能在密封类声明的文件之外继承它。 密封类常用于表示一组受限的、相关的类,例如状态、事件或者消息类型。 密封类的主要用途之一是提供更强的类型安全性,在 when 表达式中尤为明显。当你使用密封类时,编译器可以确保你已经覆盖了所有可能的子类,从而避免使用 else 分支或者处理未预期的类型。
sealed class OrderStatus {
object Pending : OrderStatus ( )
object Shipped : OrderStatus ( )
object Delivered : OrderStatus ( )
object Cancelled : OrderStatus ( )
}
fun printOrderStatus ( status: OrderStatus) {
when ( status) {
is OrderStatus. Pending -> println ( "Order is pending." )
is OrderStatus. Shipped -> println ( "Order has been shipped." )
is OrderStatus. Delivered -> println ( "Order has been delivered." )
is OrderStatus. Cancelled -> println ( "Order has been cancelled." )
}
}
fun main ( ) {
val status = OrderStatus. Shipped
printOrderStatus ( status)
}