kotlin学习(一)

怎么定义一个类

如果你想定义一个类,你只需要使用class关键字。

class MainActivity{

}

它有一个默认唯一的构造器。我们会在以后的课程中学习在特殊的情况下创建其它额外的构造器,但是请记住大部分情况下你只需要这个默认的构造器。你只需要在类名后面写上它的参数。如果这个类没有任何内容可以省略大括号:

class Person(name: String, surname: String)

那么构造函数的函数体在哪呢?你可以写在init块中:

class Person(name: String, surname: String) {
    init{
        ...
    }

}

类继承

默认任何类都是基础继承自Any(与java中的Object类似),但是我们可以继承其它类。所有的类默认都是不可继承的(final),所以我们只能继承那些明确声明open或者abstract的类:

open class Animal(name: String)
class Person(name: String, surname: String) : Animal(name)

当我们只有单个构造器时,我们需要在从父类继承下来的构造器中指定需要的参数。这是用来替换Java中的super调用的。

函数

函数(我们Java中的方法)可以使用fun关键字就可以定义:

fun onCreate(savedInstanceState: Bundle?) {
}

如果你没有指定它的返回值,它就会返回Unit,与Java中的void类似,但是Unit是一个真正的对象。你当然也可以指定任何其它的返回类型:

fun add(x: Int, y: Int) : Int {
    return x + y
}

小提示:分号不是必须的

就像你在上面的例子中看到的那样,我在每句的最后没有使用分号。当然你也可以使用分号,分号不是必须的,而且不使用分号是一个不错的实践。当你这么做了,你会发现这节约了你很多时间。

然而如果返回的结果可以使用一个表达式计算出来,你可以不使用括号而是使用等号:

fun add(x: Int,y: Int) : Int = x + y

构造方法和函数参数

Kotlin中的参数与Java中有些不同。如你所见,我们先写参数的名字再写它的类型:

fun add(x: Int, y: Int) : Int {
    return x + y
}

我们可以给参数指定一个默认值使得它们变得可选,这是非常有帮助的。这里有一个例子,在Activity中创建了一个函数用来toast一段信息:

fun toast(message: String, length: Int = Toast.LENGTH_SHORT) {
    Toast.makeText(this, message, length).show()
}

如你所见,第二个参数(length)指定了一个默认值。这意味着你调用的时候可以传入第二个值或者不传,这样可以避免你需要的重载函数:

toast("Hello")
toast("Hello", Toast.LENGTH_LONG)

这个与下面的Java代码是一样的:

void toast(String message){
}

void toast(String message, int length){
    Toast.makeText(this, message, length).show();
}

这跟你想象的一样复杂。再看看这个例子:

fun niceToast(message: String,
                tag: String = javaClass<MainActivity>().getSimpleName(),
                length: Int = Toast.LENGTH_SHORT) {
    Toast.makeText(this, "[$className] $message", length).show()
}

我增加了第三个默认值是类名的tag参数。如果在Java中总数开销会以几何增长。现在可以通过以下方式调用:

toast("Hello")
toast("Hello", "MyTag")
toast("Hello", "MyTag", Toast.LENGTH_SHORT)

而且甚至还有其它选择,因为你可以使用参数名字来调用,这表示你可以通过在值前写明参数名来传入你希望的参数:

toast(message = "Hello", length = Toast.LENGTH_SHORT)

小提示:String模版

你可以在String中直接使用模版表达式。它可以帮助你很简单地在静态值和变量的基础上编写复杂的String。在上面的例子中,我使用了"[$className] $message"。

如你所见,任何时候你使用一个$符号就可以插入一个表达式。如果这个表达式有一点复杂,你就需要使用一对大括号括起来:"Your name is ${user.name}"。

编写你的第一个类

我们已经有了MainActivity.kt类。这个Activity会展示下周一系列的天气预报,所有它的layout需要有些改变。

创建一个layout

显示天气预报的列表我们使用RecyclerView,所以你需要在build.gradle中增加一个新的依赖:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile "com.android.support:appcompat-v7:$support_version" 
    compile "com.android.support:recyclerview-v7:$support_version" ...
}

然后,activity_main.xml如下:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="match_parent"
             android:layout_height="match_parent">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/forecast_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</FrameLayout>

Mainactivity.kt中删除掉之前用来测试的能正常运行的所有代码(现在应该会提示错误)。暂且我们使用老的findViewByid()的方式:

val forecastList = findViewById(R.id.forecast_list) as RecyclerView
forecastList.layoutManager = LinearLayoutManager(this)

如你所见,我们定义类一个变量并转型为RecyclerView。这里与Java有点不同,我们会在下一章分析这些不同之处。LayoutManager会通过属性的方式被设置,而不是通过setter,这个layout已经足够显示一个列表了。

对象实例化

对象实例化也是与Java中有些不同。如你所见,我们去掉了new关键字。这时构造函数仍然会被调用,但是我们省略了宝贵的四个字符。LinearLayoutManager(this)创建了一个对象的实例。

The Recycler Adapter

我们同样需要一个RecyclerView的Adapter。之前我在我博客中讨论过RecyclerView,如果你以前没有使用过,它可能会有所帮助。

RecyclerView中所使用到的布局现在只需要一个TextView,我会手动去创建这个简单的文本列表。增加一个名为ForecastListAdapter.kt的Kotlin文件,包括如下代码:

class ForecastListAdapter(val items: List<String>) :
        RecyclerView.Adapter<ForecastListAdapter.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(TextView(parent.context))
    }
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.textView.text = items.[position]
    }

    override fun getItemCount(): Int = items.size

    class ViewHolder(val textView: TextView) : RecyclerView.ViewHolder(textView)
}

又是如此,我们可以像访问属性一样访问context和text。你可以保持以往那样操作(使用getters和setters),但是你会得到一个编译器的警告。如果你还是倾向于Java中的使用方式,这个检查可以被关闭。但是一旦你使用上了这种属性调用的方式你就会爱上它,而且它也节省了额外的字符总量。

回到MainActivity,现在简单地创建一系列的String放入List中,然后使用创建分配Adapter实例。

private val items = listOf(
    "Mon 6/23 - Sunny - 31/17",
    "Tue 6/24 - Foggy - 21/8",
    "Wed 6/25 - Cloudy - 22/17",
    "Thurs 6/26 - Rainy - 18/11",
    "Fri 6/27 - Foggy - 21/10",
    "Sat 6/28 - TRAPPED IN WEATHERSTATION - 23/18",
    "Sun 6/29 - Sunny - 20/7"
    )

override fun onCreate(savedInstanceState: Bundle?) {
    ...
    val forecastList = findViewById(R.id.forecast_list) as RecyclerView
    forecastList.layoutManager = LinearLayoutManager(this) 
    forecastList.adapter = ForecastListAdapter(items)
}

List的创建

尽管我会在本书后面来对Collection进行讲解,但是我现在仅仅简单地解释你可以通过使用一个函数listOf创建一个常量的List(很快我们就会讲到的immutable)。它接收一个任何类型的vararg(可变长的参数),它会自动推断出结果的类型。

还有很多其它的函数可以选择,比如setOfarrayListOf或者hashSetOf

为了优化项目的结构,我也移动了一些类到新的包里面。

我们在上面很简短的代码中看到了很多新的东西,所以我会在下一章讲到它们。我们现在必须要学习一些比如基本类型,变量,属性等比较重要的概念才能继续下去。

后续的文章可以去我的博客里面看。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值