转向Kotlin——类和接口

类的声明

和Java没有什么两样,Kotlin中,类的声明也使用class关键字,如果只是声明一个空类,Kotlin和Java没有任何区别,不过定义类的其他成员,区别就很大了。

class MyClass{
}
复制代码

类的构造器

构造器也叫构造方法,是类创建的必要元素。

1、主构造器

面向对象语言在定义类的时候,都需要至少制定一个构造方法,如果不指定构造器,编译器会默认生成一个不带任何参数的构造器,这是传统面向对象语言的做法。

Kotlin会有一些不一样的地方,在Kotlin中,类允许定义一个主构造器,和若干个第二构造器。主构造器是类头的一部分,紧跟在类名的后面,参数是可选的。如下代码定义了一个类,并指定了一个主构造器。

class Person constructor(name: String) {
    
}
复制代码

如果主构造器没有任何注解,任何修饰,constructor可以省略

class Person(name: String) {

}
复制代码

上面的代码只是声明了主构造器,是在哪里实现构造器呢?如果是主构造器,需要在init代码块中进行初始化主构造器:

class Person(name: String) {

	val myName = name
	
    init {
        println(name)
    }
    
}
复制代码

注意:主构造器中的参数不仅可以在init代码块中使用,还可以对类的属性进行初始化。

var和val也可以修饰主构造器参数,如果使用var,表示参数对于构造器来说是变量,在构造器内部可以对其进行操作和改变;如果使用val,表示该参数是常量,在构造器中不能修改它的值。但要注意的是,var修饰的参数,在主构造器中修改值后,并不会把修改后的值传到对象外面。

class Person(var name: String) {

    init {
        name="haha"
        println(name)
    }
    
}
复制代码

2、第二构造器

Kotlin的类中,除了可以声明一个主构造器之外,还可以声明若干个第二构造器,第二构造器必须在类中声明,前面必须加constructor关键字

class Person(var name: String) {

    init {
        name = "hello"+ name
        println(name)
    }


    constructor(age: Int) : this("js") {
        println(name + " " + age)
    }
    
    constructor(sex : Byte) :this(20){
        println(name +" "+ sex)
    }
}
复制代码

明了主构造器,那么所有的第二构造器必须在声明的后面调用主构造器,或者通过另外一个第二构造器间接地调用主构造器。

当然,如果类中并没有声明主构造器,第二构造器后面可以不调用主构造器。

上面Person类中一共定义了三个构造器,就涉及到了构造器的重载,也就是一个类中拥有不同个参数和参数类型的构造器。

注意:主构造器中可以使用var和val修饰参数,但第二构造器中不能使用,也就意味着第二构造器中的参数都是只读的。

3、Kotlin的单例模式

我们只是大概了解以下Kotlin的单例模式如何书写,后面会详细介绍。

class Singleton private constructor() {
    public var value: Singleton? = null

    private object mHolder {
        val INSTANCE = Singleton()
    }

    companion object Factory {
        fun getInstance(): Singleton {
            return mHolder.INSTANCE
        }
    }
}
复制代码

4、函数中的默认参数

有很多变成语言是支持默认参数的,也就是在调用函数的时候不指定参数值,就会使用默认的参数值。Java不支持,但Kotlin是支持的,先看个例子:

class Class(param: Int, param1: String = "js") {

}
复制代码

在创建Class对象时,可以只传第一个参数,第二个参数可以不传,如Class(5),其第二个参数默认为"js"。

由于Kotlin支持默认参数,所以没有必要非要定义一个没有参数的构造器,可以直接定义一个所有参数都有默认值的构造器。

5、创建类实例

创建Kotlin实例在之前已经用到过了。对于大都数面向对象的语言来说,创建类实例的时候都会用到new关键字,但Kotlin中不再需要,直接调用构造器即可,如MyClass()。

类成员

1、属性的基本用法

Java开发者对JavaBean一定特别熟悉,其实JavaBean就是一个普通的Javak类,关键在于对属性的get和set方法。当然Java可以直接使用public的成员变量来解决这个问题,但对于属性来说,不仅仅能读写其值,还需要对其进行二次加工,所以get/set也是必须的。

Kotlin中的属性语法,只有var/val和属性名时必须的,其他都是可选的。也就是说,Kotlin属性最简单的形式就是在类中定义一个变量(var)或常量(val),要引用属性,就像引用变量一样。

class Class{

    var name:String="js"
    val int:Int=2
    
    fun pri(){
        println("name=${name} int=${int}")
    }
    
}
复制代码

2、属性的get/set方法

因为Kotlin支持属性语法,所以并不需要对每个单独定义get和set方法。如果属性只是可读的(val),只需添加一个get方法,如果属性是读写的,添加get和set方法。g如果get/set方法只有一行代码,直接用=分隔即可,如果有多行代码,则z使用{}处理:

class Class {

    var name: String
        get() = name
        set(value) {
            name = value
        }

    val age: Int
        get() = age

}
复制代码

3、保存属性值的字段

Kotlin中可以使用filed标识符当作成员变量使用,也就是通过filed读写属性值:

class Class {

    var name: String = "js"
        get() = field
        set(value) {
            field = value
        }

}
复制代码

4、函数

Kotlin中,函数既可以在类外部定义,也可以在类的内部定义。如果是前者,是全局函数,如果是后者,是类成员函数。但无论定义在哪里,语法都是一样的。

说到构造器时,构造器支持默认参数值,实际上,函数也支持默认参数值。要注意的是,带默认值的参数必须是最后几个参数,也就是说,如果某个参数带有默认值,那么该参数后面的所有参数必须都有默认值:

class Class {

    fun func(url: String, host: String = "www.baidu.com") {

    }

}
复制代码

但是如果带默认值的参数过多,在调的时候也会带来一些麻烦,如下:

class Class {

    fun func(url: String, host: String = "www.baidu.com", name: String = "haha") {

    }

}
复制代码

当我想调用func方法,host参数使用默认值,而name参数自定义,就不得不在调用方法的时候将host参数显示地传"www.baidu.com"。为了解决这个问题,Kotlin允许使用命名参数传递参数值,所谓命名参数,就是在调用函数的时候指定形参名(host、name),这样就可以直接为指定的参数传值了,如:

Class().func("hh",name="hello")
复制代码

如果传入函数的参数个数不固定,可以使用可变参数,可变参数用vararg关键字声明:

class Class {

    fun func(url: String, host: String = "www.baidu.com", name: String = "haha") {

    }

    fun func2(vararg names: String) {
        for (name in names) {
            println(name)
        }
    }
}
复制代码

很多时候,函数体中只有一行代码,用传统的写法就比较麻烦了,这时可以直接在函数声明后加等号(=),后面直接跟代码,这种方式可以省略函数返回值类型

class Class {

    var value: Int = 1

    fun func(url: String, host: String = "www.baidu.com", name: String = "haha") {

    }

    fun func2(vararg names: String) {
        for (name in names) {
            println(name)
        }
    }

    fun func3() = value
}
复制代码

同时,在函数体内也可以定义函数,这种函数叫做本地函数,不再累赘。

5、嵌套类

所谓嵌套类,就是直接在n类内部再定义一个类。

class People {
    class Student {
        
    }
}

People.Student()
复制代码

内部类还可以用inner声明,表示可以通过外部类的实例进行调用:

class People {
    inner class Student {

    }
}

People().Student()
复制代码

修饰符

Kotlind的修饰符一共四个:private、protected、internal和public

  • private:仅在类的内部可以调用;
  • protected:类似private,但在子类中也可以访问;
  • internal:模块中的任何类都可以调用;
  • public:任何类都可以访问。

如果不指定修饰符,默认全是public的,这些修饰符可以用在普通的类中,也可以用在构造器中。

类的继承

1、如何继承

与Java不同,Kotlin类的继承需要使用冒号(:),而Java使用extends。注意,冒号后面需要调用父类的构造器。

Kotlin和Java一样,都是单继承的,也就是说,一个Kotlin类只能有一个父类。要注意的是,Kotlin类默认是final的,也就是不允许继承的,需要显示地用open关键字声明,表示此类可以被继承。

open class School {

}

class MiddleSchool : School() {

}
复制代码

2、重写方法

Kotlin中不仅类默认是不可以被继承的,连方法默认也是不可以重写的。因此,如果要在子类中重写方法啊,那么父类的对应方法必须用open修饰,而且要在子类重写的方法前面加override关键字:

open class School {
    open fun func() {

    }
}

class MiddleSchool : School() {
    override fun func() {

    }
}
复制代码

如果一个方法已经被override修饰了,那么这个方法已经就被重写了,依然可以被它的子类所重写。

3、重写属性

属性的重写与方法类似,被重写的属性也必须用open修饰,子类属性必须用override修饰。不过要注意,val属性可以被重写为var属性,但反过来不可以:

open class School {

    open val name: String = "School"

    open fun func() {

    }
}

class MiddleSchool : School() {

    override var name: String = "MiddleSchool"

    override fun func() {

    }
}
复制代码

接口

接口是另一个重要的面向对象元素,用于制定规范,强调对象是否具有某个功能。

Kotlin与Java类似,使用interface声明接口,一个类可以实现多个接口,实现的方法和类继承相同,而且,接口中的属性和方法都是open的

interface MyInterface {
    fun func()

    fun func2(): String {
        return "js"
    }
}

class MyClass : MyInterface {
    override fun func() {
        
    }

}
复制代码

上述代码中可以看出:实现接口与继承父类类似,使用冒号(:),但后面不是调用构造方法,而是是指跟接口名;Kotlin中的接口的方法,允许包含默认方法体,对于这样的额方法,子类实现接口时不一定必须实现该方法。

抽象类

抽象类和接口非常相似,抽象类不能被实例化,需要abstract关键字声明,抽象类实现接口后,接口中没有函数体的函数可以不重写,接口中的这些方法自动被继承到子类中,称为抽象方法:

abstract class MyAbsClass{
    abstract fun f()
}
复制代码

抽象方法没必要用open声明,因为抽象类本身就是可以被继承的。

小结

Kotlin中的类e和接口与Java中的本质上没有什么两样,只不过Kotlin为了体现差异,加入了一些语法糖,如接口允许函数带函数体,支持属性,不支持静态方法等。我们需要慢慢去熟悉它。

更多精彩内容,欢迎关注我的微信公众号——Android机动车

<think>嗯,用户之前有一些C语言基础,想学面向对象编程,同时关注就业市场。我之前推荐了Java、PythonC++,并分析了各自的市场需求优势。现在用户提到站内引用中关于KotlinJava的对比信息,并具体问掌握C++后学习JavaKotlin的难度速度。用户可能有这样的思考过程:已经掌握C++这个较难的系统级语言,想评估转向更主流的应用层语言需要付出的学习成本。特别是看到引用中Kotlin被描述为"更实用""编译稍慢",可能犹豫是否要跳过Java直接学Kotlin。深层需求或许是想用最少的精力获得最大的就业竞争力。需要对比三种语言的特性差异。C++程序员习惯手动内存管理、多继承、复杂模板等概念,而Java/Kotlin采用更简单的自动内存管理(GC)、单继承+接口、泛型等设计。根据引用[3][4],Java的强结构化特性确实更适合大型项目,而Kotlin的coroutines(引用[1])简洁语法(引用[2])则带来开发效率提升。学习曲线方面,从C++转Java会感觉语法简化但约束变多,比如所有必须继承Object、没有运算符重载等。而KotlinJava基础上进一步简化(如空安全设计、数据),但编译时型推断函数式语法可能带来新学习点。速度上,如果用户熟悉C++的OOP基础,Java核心语法约2周可掌握,Kotlin约1个月(需适应新范式)。就业市场优先级仍需强调Java的主导地位(引用[1][4]),尽管Kotlin在安卓开发增长快。可以建议"先JavaKotlin"的路径,既符合企业技术栈现状,又能利用语言共性减少重复学习。最后需回应隐藏疑虑:用户可能担心学Java会过时。实际上Java的虚拟机生态(JIT优化、跨平台——引用[4])Spring框架仍是企业主流,而Kotlin更像是效率工具补充。就像C++程序员会学Rust但不放弃C++一样,双语言组合才更具竞争力。</think> 基于您的C++基础引用资料,从C++转向JavaKotlin的学习难度效率可分析如下: --- ### **语言特性对比** | 维度 | C++ | Java | Kotlin | |----------------|--------------------|--------------------|---------------------| | **内存管理** | 手动控制(new/delete) | GC自动回收[^4] | GC自动回收[^3] | | **空安全** | 指针可为null | @Nullable注解 | 编译时空检查(内置)[^2] | | **并发模型** | 线程/锁 | 原生Thread | 协程(Coroutines)[^1] | | **语法复杂度** | 高(多继承/运算符重载) | 中(单继承+接口) | 低(数据/扩展函数)[^2] | | **编译速度** | 中低速 | 高速 | 中低速[^1] | --- ### **学习难度与效率分析** #### **1. 转向Java的路径** - **优势** - **自动内存管理**:无需手动释放对象(`delete` → GC回收),减少80%内存泄漏风险[^4] - **简化语法**:移除指针运算、运算符重载等复杂特性,核心语法学习周期**缩短40%** - **强型系统**:与C++的静态型高度兼容(需适应`Integer`等包装) - **挑战** - **泛型差异**:Java泛型采用型擦除(C++模板在编译时实例化) - **生态适应**:需学习JVM、Spring等企业级框架 > **学习效率**:C++开发者约**2~3周**可掌握Java核心语法,**2个月**达到开发级熟练度。 #### **2. 转向Kotlin的路径** - **优势** - **语法简洁性**:数据(`data class`)、空安全(`?`操作符)等特性减少50%样板代码[^2][^3] - **函数式支持**:Lambda表达式/扩展函数更接近现代语言(似C++11后的特性) - **协程替代多线程**:简化异步编程(对比C++的`std::thread`复杂管理)[^1] - **挑战** - **编译速度下降**:大量语法糖导致编译耗时高于Java[^1] - **范式转换**:需接受"一切皆表达式"、不可变变量(`val`)等函数式思维 > **学习效率**:已有Java基础者**1~2周**可上手Kotlin;**直接从C++转需3~4周**(需同时适应JVM)。 --- ### **关键学习策略** 1. **优先掌握Java核心** ```java // C++ → Java 关键映射 std::vector<T> → ArrayList<T> // 集合 virtual void f() → interface + @Override // 多态 delete obj; → obj = null; // GC自动回收 ``` 2. **渐进式切入Kotlin** ```kotlin // KotlinJava的简化示例 data class User(val name: String, val age: Int) // 自动生成equals/hashCode user?.address?.city // 空安全链式调用(避免NullPointerException) ``` 3. **利用C++底层理解** - JVM垃圾回收机制(如分代收集)可通过C++的内存布局知识加速理解 - Kotlin/Native支持编译为原生二进制(似C++)[^3],降低迁移抗拒感 --- ### **就业市场建议** - **短期求职**:主攻**Java+Spring生态**(占JVM岗位85%以上[^4]) - **长期发展**:掌握Java后补充**Kotlin(安卓/后端Ktor)**,薪资溢价达10%~15%[^2] - **领域选择**: $$ \text{选型建议} = \begin{cases} \text{金融/电商} & \to \text{Java} \\ \text{安卓开发} & \to \text{Kotlin} \\ \text{高性能计算} & \to \text{保留C++} \end{cases} $$ ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值