类和接口
类
类的定义
Java
public class SimpleClass {
}
Kotlin
class SimpleClass
在kotlin中默认是public的,并且如果没有内容{}也是可以省略的
接下来我们看下在类中定义成员
Java
public class SimpleClass {
public int x;
public void y(){
}
}
Kotlin
class SimpleClass {
var x: Int = 0
fun y() {}
}
在Java中,成员变量是有默认值的,但是在Kotlin中,我们必须要给它初始化设置个默认值
接下来我们看下怎么定义构造方法
Java
public class SimpleClass{
public int x;
public SimpleClass(int x) {
this.x = x;
}
public void y(){
}
}
Kotlin
第一种:
class SimpleClass {
var x: Int
constructor(x: Int) {
this.x = x
}
fun y() {}
}
和Java写法很像,使用constructor修饰,它还可以简化下
class SimpleClass constructor(x: Int) {
var x: Int = x
fun y() {}
}
就是把构造方法挪到类定义那里,kotlin里面有主构造区和副构造器一说,这么定义就是主构造器,上面那种使用constructor定义的就是副构造区,主构造器要求所有的其他构造器都调用它,上面那种写法还可以再简单点,直接把constructor省略
class SimpleClass(x: Int) {
var x: Int = x
fun y() {}
}
既然我们想定义成员属性我们构造器中的一样,我们还可以简化下
class SimpleClass(var x: Int) {
fun y() {}
}
这就相当于我们在类里面定义了一个x,它等于我们构造器中的x
那怎么实例化类呢?
Java
SimpleClass simpleClass = new SimpleClass(9);
System.out.println(simpleClass.x);
simpleClass.y();
Kotlin
val simpleClass = SimpleClass(9)
println(simpleClass.x)
simpleClass.y()
在Kotlin中不需要new这个关键字了
接口
接口的定义
Java
public interface SimpleInf {
void simpleMethod();
}
Kotlin
interface SimpleInf {
fun simpleMethod()
}
接口实现
Java
public class SimpleClass
implements SimpleInf {
@Override
public void simpleMethod() {
}
}
Kotlin
class SimpleClass : SimpleInf {
override fun simpleMethod() {}
}
在Kotlin中使用:代替implements关键字,同时必须使用override修饰要实现的方法
抽象类定义
Java
public abstract class AbsClass {
public abstract void absMethod();
protected void overridable(){ }
public final void nonOverridable(){ }
}
Kotlin
abstract class AbsClass {
abstract fun absMethod()
open fun overridable(){}
fun nonOverridable(){}
}
这里要注意:在Java中,我们在抽象类中定义普通方法,子类是可以选择性的进行实现,但是在Kotlin中,如果在抽象类中定义的普通方法前面没有加上open修饰,那么子类就不能进行实现这个方法!
抽象类的实现
Java
public class SimpleClass
extends AbsClass
implements SimpleInf {
@Override
public void simpleMethod() {
}
@Override
public void absMethod() {
}
}
Kotlin
class SimpleClass
: AbsClass(), SimpleInf {
override fun absMethod() {}
override fun simpleMethod() {}
fun y() {}
}
在Kotlin中一样使用:代替extends,同时要实现的抽象方法必须使用override修饰
这里我们就需要注意上面说的,没有用open修饰的方法是不能实现的
同样的还有类的继承,比如我们想继承这个SimpleClass,如果它前面不用open修饰,我们是不能继承的
我们假如在接口里面定义一个属性
interface SimpleInf {
val simpleProperty: Int // property
fun simpleMethod()
}
我们子类实现这个接口后就需要对这个属性提供一个getter方法
override val simpleProperty: Int
get() {
return 2
}
在Kotlin中,属性就相当于一个值加上对应的get/set方法
我们在举例说明下,假设有一个Person类,有age和name两个属性
java
public class Person {
private int age; //field
private String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Kotlin
class Person(age: Int, name: String) {
var age: Int = age //property
var name: String = name
}
我们发现没有get/set方法了,我们也可以把它们暴露出来
class Person(age: Int, name: String) {
var age: Int = age //property
get() {
return field
}
set(value) {
field = value
}
var name: String = name
get() {
return field // backing field
}
set(value) {
field = value
}
}
扩展方法
我们在使用某个类的时候经常会想要是这个类有xxx方法就好了对吧!在Java中我们一般是直接新建几个工具类来扩展某个类的方法,在Kotlin中不需要,我们可以直接对某个类进行扩展方法和属性
class PoorGuy{
var pocket: Double = 0.0
}
我们想在PoorGuy类中定义一个方法,我们可以直接这么 定义
fun PoorGuy.noMoney(){
}
使用起来跟普通方法一样
fun main() {
var guy = PoorGuy()
guy.noMoney()
}
定义属性和定义方法差不多
var PoorGuy.moneyLeft: Double
get() {
return this.pocket
}
set(value) {
pocket = value
}
空类型安全
这个在Java中是没有的,我们在Java中声明一个String类型的变量,我们是可以给他赋值为null的
public static void main(String[] args) {
String x = "Hello";
x = null;
}
但是在Kotlin中是不允许的,编译器会报错
那我们既然要兼容Java,想接受一个null怎么办呢?我们可以在类型后面加个?
var nullable: String? = "Hello"
nullable=null
如果我们想使用这个变量,我们就需要机型强转,要不然会报错
怎么强转呢?加!!即可
var nullable: String? = "Hello"
val length = nullable!!.length
这种方法比较暴力,我们一开始就知道它不为空,如果我们不知道它知否为空的话我们就需要下面那样
val length = nullable?.length ?: 0
接下来我们看下空类型继承关系
var x: String = "Hello"
var y: String? = "World"
// x = y // Type mismatch
y = x // OK
这里也就是说String是String?的子类
智能类型转换
假设有两个类Person和Kotliner,Person是Kotliner子类,Person中有一个属性name
Java
Kotliner kotliner = new Person("xiaoming", 20);
if(kotliner instanceof Person){
System.out.println(((Person) kotliner).name);
}
上面是Java代码,我们已经通过instanceof判断了kotliner的类型,使用的时候我们依旧还需要强转下
Kotlin
val kotliner: Kotliner = Person("benny", 20)
if(kotliner is Person){
println(kotliner.name)
}
不支持智能转换情况
var tag: String? = null
fun main() {
if(tag != null){
println(tag.length)
}
}
因为我们在调用println(tag.length)的时候,有可能别的线程改变了tag的值
使用Retrofit发起网络请求
首先添加相关依赖
implementation "com.squareup.retrofit2:retrofit:2.6.2"
implementation "com.squareup.retrofit2:converter-gson:2.6.2"
implementation "com.google.code.gson:gson:2.8.1"
我们请求的地址就是https://api.github.com/repos/JetBrains/Kotlin
它的返回值,这里就不截全了,我们只是演示怎么使用
接下来就开始写具体代码了(Retrofit基本使用可以百度下)
首先我们要先创建一个Repository类
data class Repository(
var id: Int,
var node_id: String,
var name: String,
var full_name: String,
var private: Boolean,
var owner: Owner,
var html_url: String,
var description: String,
var fork: Boolean,
var url: String,
var forks_url: String,
var keys_url: String,
var collaborators_url: String,
var teams_url: String,
var hooks_url: String,
var issue_events_url: String,
var events_url: String,
var assignees_url: String,
var branches_url: String,
var tags_url: String,
var blobs_url: String,
var git_tags_url: String,
var git_refs_url: String,
var trees_url: String,
var statuses_url: String,
var languages_url: String,
var stargazers_url: String,
var contributors_url: String,
var subscribers_url: String,
var subscription_url: String,
var commits_url: String,
var git_commits_url: String,
var comments_url: String,
var issue_comment_url: String,
var contents_url: String,
var compare_url: String,
var merges_url: String,
var archive_url: String,
var downloads_url: String,
var issues_url: String,
var pulls_url: String,
var milestones_url: String,
var notifications_url: String,
var labels_url: String,
var releases_url: String,
var deployments_url: String,
var created_at: String,
var updated_at: String,
var pushed_at: String,
var git_url: String,
var ssh_url: String,
var clone_url: String,
var svn_url: String,
var homepage: String,
var size: Int,
var stargazers_count: Int,
var watchers_count: Int,
var language: String,
var has_issues: Boolean,
var has_projects: Boolean,
var has_downloads: Boolean,
var has_wiki: Boolean,
var has_pages: Boolean,
var forks_count: Int,
var mirror_url: Any,
var archived: Boolean,
var disabled: Boolean,
var open_issues_count: Int,
var license: Any,
var forks: Int,
var open_issues: Int,
var watchers: Int,
var default_branch: String,
var organization: Organization,
var network_count: Int,
var subscribers_count: Int
) {
data class Owner(
var login: String,
var id: Int,
var node_id: String,
var avatar_url: String,
var gravatar_id: String,
var url: String,
var html_url: String,
var followers_url: String,
var following_url: String,
var gists_url: String,
var starred_url: String,
var subscriptions_url: String,
var organizations_url: String,
var repos_url: String,
var events_url: String,
var received_events_url: String,
var type: String,
var site_admin: Boolean
)
data class Organization(
var login: String,
var id: Int,
var node_id: String,
var avatar_url: String,
var gravatar_id: String,
var url: String,
var html_url: String,
var followers_url: String,
var following_url: String,
var gists_url: String,
var starred_url: String,
var subscriptions_url: String,
var organizations_url: String,
var repos_url: String,
var events_url: String,
var received_events_url: String,
var type: String,
var site_admin: Boolean
)
}
这里我们在class前面加上了一个data修饰符,这个后面我们会讲解,表示这个类是数据类
然后我们就要写一个接口类
interface GitHubApi {
@GET("/repos/{owner}/{repo}")
fun getRepository(@Path("owner") owner: String, @Path("repo") repo: String): Call<Repository>
}
然后就是具体的调用了
fun main() {
val gitHubApi = Retrofit.Builder().baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(GitHubApi::class.java)
val response = gitHubApi.getRepository("JetBrains", "Kotlin").execute()
val repository = response.body()
if(repository == null){
println("Error! ${response.code()} - ${response.message()}")
} else {
println(repository.name)
println(repository.owner.login)
println(repository.stargazers_count)
println(repository.forks_count)
println(repository.html_url)
}
}
使用起来跟Java差不多,相对来说就是简单了一些