kotlin學習--類的延申

一迟几、內部類

在現實開發(fā)中消请,內部類出現的場景可以說非常多,例如类腮,adapter(適配器)中的viewHolder臊泰、數據模型中也有可能出現一個或者多個對象,這里的對象就是一個內部類蚜枢。讓我們來了解下內部類哩缸逃。

1.1.嵌套類

所謂的嵌套類,通俗來講就是一個類嵌套在另一個類里面
eg:

/**
 * 嵌套類
 */
 private var name = "biao"
    fun outdoorMethou(){
        //nesteMethou()//無法直接調用嵌套類的成員
        //只能通過實例嵌套類來調用
        val nestingClass = NestingClass()
        nestingClass.nesteMethou()
    }

    class NestingClass{
        fun nesteMethou(){
            //println("name:$name")//無法使用外部類的成員
            println("to do something magic")
        }
    }

fun main(args:Array<String>){
    val nestingClass = OutdoorClass.NestingClass()
    nestingClass.dowhat()
}

reslut:

to do something magic

說明:

  • 嵌套類相當于Java中的靜態(tài)內部類厂抽,但是在kotlin中完全取消了static關鍵字需频,所以在kotlin類中,除了嵌套類筷凤,其余都是非靜態(tài)成員
  • 在Java中靜態(tài)成員是不能訪問非靜態(tài)成員的贺辰,參考于此,可以解釋在嵌套類中不能訪問外部類的成員嵌施,但是可以訪問其他嵌套類
  • 跟內部類一樣饲化,外部類不能直接調用嵌套類成員,如需調用吗伤,需創(chuàng)建嵌套類對象吃靠,通過對象調用嵌套類成員
  • 調用嵌套類的屬性或方法的格式為:外部類.嵌套類().嵌套類方法/屬性。在調用的時候嵌套類是需要實例化的足淆。

1.2.內部類

內部類相當于Java中沒有用static修飾的內部類巢块,使用關鍵字:inner
eg:

class OutClass{

    //外部類的私有屬性可以被內部類使用
    private var name = "xie"
    //外部類的私有函數可以被內部類使用
    private fun outFun(){
        println("i am outFun")
    }

    //通過此方法實例化內部類,再調用內部類方法
    fun getInnerClassTodo(){
        //innerFun()//這種外部類直接調用內部類成員的方式是編譯不通過的巧号,因為此時根本不存在內部類的對象
        val innerClass = InnerClass()
        //外部類想調用內部類族奢,需實例化內部類
        innerClass.innerFun()
    }

    inner class InnerClass{
        var age = 20

        fun innerFun(){
            println("name:$name+age:$age")
            outFun()
        }
    }
}

fun main(args:Array<String>){
    val innerClass = OutClass().InnerClass()
    innerClass.innerFun()
}

reslut:

name:xie+age:20
i am outFun

說明:

  • 外部類的成員可以被內部類使用,外部類無法直接使用內部類成員丹鸿,只能通過實例化內部類成員
  • 調用內部類的屬性或方法的格式為:外部類().內部類().內部類方法/屬性越走。在調用的時候外部類、內部類都是需要實例化的。

1.3.匿名內部類

在實際開發(fā)中廊敌,匿名內部類并不陌生铜跑,隨處可見,像view的點擊事件:OnClickListener骡澈,多線程的實現锅纺。
其實匿名內部類就是一個沒有名字的內部類,通常用來簡化代碼肋殴,使用匿名內部類的前提條件是:必須繼承一個父類或者實現一個接口
eg:

/**
 * 定義一個接口
 */
interface OnClickListener{
    fun onItemClick(str : String)
}

/**
 * 匿名內部類
 */
class AnonymousClass{
    lateinit private var listener : OnClickListener

    fun setOnClickListener(listener: OnClickListener){
        this.listener = listener
    }

    fun testListener(){
        listener.onItemClick("我是匿名內部類的測試方法")
    }
}

fun main(args:Array<String>){
    val anonymousClass = AnonymousClass()
    anonymousClass.setOnClickListener(object :OnClickListener{
        override fun onItemClick(str: String) {
            println("to do something")
        }
    })
}

1.4.局部類

局部類:跟Java一樣囤锉,就是在方法中的類
eg:

class LocalClass{

    var numOut = 1

    fun partMouth(){

        var name = "partMouth"

        class PartClass{
            var numPart : Int = 2

            fun test(){
                name = "PartClass"
                numOut = 3
                numPart = 4
                println("我是局部類中的方法")
            }
        }

        val partClass = PartClass()
        println("name = $name \t numPart = " + partClass.numPart + "\t numOut = $numOut")
        partClass.test()
        println("name = $name \t numPart = " + partClass.numPart + "\t numOut = $numOut")
    }
}

fun main(args:Array<String>){
    val localClass = LocalClass()
    localClass.partMouth()
}

result:

name = partMouth     numPart = 2     numOut = 1
我是局部類中的方法
name = PartClass     numPart = 4     numOut = 3

說明:

  • 局部類只能在定義該局部類的方法中使用。
  • 定義在實例方法中的局部類可以訪問外部類的所有變量和方法护锤。也能修改
  • 局部類中的可以定義屬性官地、方法。并且可以修改局部方法中的變量蔽豺。

二区丑、抽象類

在我們日常開發(fā)中拧粪,一般會需要寫一個基類修陡,封裝一些方法以及處理一些共有的邏輯,只是不同的類會因其不同的功能實現不同的代碼可霎。就這樣的一個基類魄鸦,一般都是一個抽象類

2.1.抽象類的定義

抽象類:可以理解為一個模板,所有的子類根據這個模板填充自己的代碼

2.1.1 關鍵字

跟Java一樣癣朗,kotlin抽象類的關鍵字也是abstract
在這里我們需要注意的是抽象分為抽象類拾因、抽象函數和抽象屬性,而一個抽象類和一個普通類的區(qū)別就在于抽象類的除了可以有其自己的屬性旷余、構造函數和函數等組成部分绢记,還包含了抽象函數和抽象屬性。
eg:

abstract class AbstractClass {
    //自身的屬性
    var tag = this.javaClass.simpleName

    //自身的方法
    fun simpleFun():Unit{//Unit相當于java中的void正卧,表示沒有返回值蠢熄,可以省略不寫
        TODO("do something")
    }

    //抽象屬性和方法
    abstract var string:String
    abstract fun init()
}

class ChildrenClass : AbstractClass() {
    //不是抽象類的子類必須實現父類的方法和屬性
    override var string: String
        get() = tag
        set(value) {}

    override fun init() {
        println("Implementing parent class methods,Obtain tag:$string")
    }
}

abstract class AbsChildrenClass : AbstractClass(){
    //抽象子類可不用實現父類的方法和屬性
    var name = this.javaClass.simpleName
    abstract fun check()
}

class absExtend : AbsChildrenClass(){
    var className = this.javaClass.simpleName
    override var string: String
        get() = name
        set(value) {}

    override fun init() {
        println("name:$name")
    }

    override fun check() {
        if (className == string) println("do something")
        else println("Nothing can be done")
    }
}

fun main(args : Array<String>){
    //抽象類不能直接實例化
    //val abstractClass = AbstractClass()//Cannot create an instance of an abstract class
    val childrenClass = ChildrenClass()
    var abstractClass:AbstractClass = ChildrenClass()//若要實現抽象類的實例化炉旷,需要依靠子類采用向上轉型的方式處理
    val absExtend = absExtend()

    childrenClass.init()
    absExtend.init()
    absExtend.check()
}

result:

Implementing parent class methods签孔,Obtain tag:ChildrenClass
name:absExtend
do something

小結:

  • 抽象類本身具有普通類特性,以及組成部分窘行。不過值得注意的是饥追,抽象類不能直接被實例化
  • 抽象類是為其子類定義了一個模板。不同是類實現不同的功能
  • 若普通類繼承了抽象類罐盔,需全部重寫父類的抽象方法和屬性但绕,如子類是抽象則不用

規(guī)則:

  • 在Kotlin中的抽象類在頂層定義的時候只能使用public可見性修飾符修飾。
  • 抽象類中可以定義內部抽象類惶看。
  • 只能繼承一個抽象類壁熄。
  • 若要實現抽象類的實例化帚豪,需要依靠子類采用向上轉型的方式處理。eg:var abstractClass:AbstractClass = ChildrenClass()
  • 抽象類可以繼承自一個繼承類草丧,即抽象類可以作為子類狸臣。不過,抽象類建議不用open修飾符修飾昌执,因為可以覆寫抽象類的父類的函數烛亦。

三、接口類

3.1 聲明以及用法

3.1.1 聲明

關鍵字:interface
定義格式:interface 接口名{
}

3.1.2 用法

關鍵字:“:”懂拾,表示實現該接口煤禽,Java不一樣的是,Java使用implement關鍵字
綜合之前我之前寫過的文章岖赋,內容使用到:的次數表示檬果,這里講一下:有哪些代表含義:
a、用于屬性的定義
b唐断、用于表示實現接口
c选脊、用戶繼承
d、用于方法返回類型定義

eg:

interface InterfaceClass{
    fun funOne()
}

class Demo:InterfaceClass{
    override fun funOne() {
        println("funOne are using")
    }
}

fun main(args: Array<String>) {
    val demo = Demo()
    demo.funOne()
}

result:

funOne are using

3.2.接口中的方法使用

eg:

interface InterfaceClass {

    fun funOne()

    fun funTwo(num: Int)

    fun funThree(num: Int): Int

    /**
     * 定義了一個有參無返回值的方法
     * 因為有結構體故可以不用重寫
     */
    fun funFour(): String {
        return "I am funFour"
    }
}

class Demo : InterfaceClass {
    override fun funOne() {
        println("funOne are using")
    }

    override fun funTwo(num: Int) {
        println("funTwo are using and parem is num:$num")
    }

    override fun funThree(num: Int): Int {
        println("funThree are using and parem is num:$num")
        return num + 1
    }

    /**
     * 接口中的funFour()方法默認返回”funFour“字符串.
     * 可以用super.funFour()返回默認值
     * 也可以不用super關鍵字脸甘,自己返回一個字符串
     */
    override fun funFour(): String {
        println("user I am funFour")
        return super.funFour()
    }
}

fun main(args: Array<String>) {
    val demo = Demo()
    demo.funOne()
    demo.funTwo(8)
    println(demo.funThree(9))
    demo.funFour()
}

result:

funOne are using
funTwo are using and parem is num:8
funThree are using and parem is num:9
10
user I am funFour
I am funFour

說明:

  • 不帶結構體的函數可以省略大括號恳啥,且不用強制重寫帶結構體的函數就可以直接調用。
  • 接口方法可以默認實現丹诀,Java8中需要一個default關鍵字钝的,kotlin只需要寫方法體就好

3.3.接口中的屬性使用

  • 在接口中申明屬性。接口中的屬性要么是抽象的铆遭,要么提供訪問器的實現硝桩。接口屬性不可以有后備字段。而且訪問器不可以引用它們枚荣。
3.3.1 作為抽象的

eg:

interface InterfaceFeild {
    var num:Int
    var name:String
}

class Demo1(override var num: Int, override var name: String) :InterfaceFeild{
    fun test(){
        println("num:$num\t+name:$name")
    }
}

fun main(args: Array<String>) {
    val demo1 = Demo1(21, "biao")
    demo1.test()
}

result:

num:21 name:biao

說明:

  • 即重寫屬性的時候是在實現類的類參數中碗脊。這也是用代碼提示去重寫的實現方法
3.3.2 作為訪問器

手動方式去重寫,并提供get方法

eg:

interface InterfaceFeild {
    var num:Int
    var name:String
    val age:Int
        get() = 2

    var number:Int
}

class Demo1(override var num: Int, override var name: String) :InterfaceFeild{

    fun test(){
        println("age:$age\tnumber:$number")
    }

    override val age: Int
        get() = super.age

    override var number: Int = 25
}

fun main(args: Array<String>) {
    val demo1 = Demo1(21, "biao")
    demo1.test()
    demo1.number = 3
    demo1.test()
}

result:

num:21  name:biao
age:2   number:25
num:21  name:biao
age:2   number:3
3.3.3 接口的沖突問題解決

該問題是指當我們在父類中聲明了許多類型棍弄,有可能出現一個方法的多種實現

eg:

interface InfOne{
    fun funTest(){
        println("I am InfOne")
    }
}

interface InfTwo{
    fun funTest(){
        println("I am InfTwo")
    }
}

class Demo2 : InfOne,InfTwo{
    override fun funTest() {
        super<InfOne>.funTest()
        super<InfTwo>.funTest()
    }

}

fun main(args: Array<String>) {
    val demo2 = Demo2()
    demo2.funTest()
}

說明:Demo4實現了InfOne和InfTwo兩個接口望薄,而兩個接口中都存在兩個相同方法名的方法。因此編譯器不知道應該選哪個呼畸,故而我們用super<接口名>.方法名來區(qū)分痕支。

四、繼承類

4.1 超類 Any

在Kotlin中蛮原,說有的類都是繼承與Any類卧须,這是這個沒有父類型的類。即當我們定義各類時,它默認是繼承與Any這個超類的

來看看Any的源碼

package kotlin

/**
 * The root of the Kotlin class hierarchy. Every Kotlin class has [Any] as a superclass.
 * 看這個源碼注釋:意思是任何一個Kotlin的類都繼承與這個[Any]類
 */
public open class Any {
    
    // 比較: 在平時的使用中經常用到的equals()函數的源碼就在這里額
    public open operator fun equals(other: Any?): Boolean
    
    // hashCode()方法:其作用是返回該對象的哈希值
    public open fun hashCode(): Int
    
    // toString()方法
    public open fun toString(): String
}

從源碼可以我們看出花嘶,它直接屬于kotlin這個包下笋籽。并且只定義了上面所示的三個方法⊥衷保或許你具有Java的編程經驗车海。在我們熟知的Java中,所有的類默認都是繼承與Object類型的隘击。而Object這個類除了比Any多了幾個方法與屬性外侍芝,沒有太大的區(qū)別。
此外埋同,從上面的源碼中我們可以看到類和函數都有open關鍵字州叠,那么這個修飾符的作用是什么呢?
來凶赁,讓我們來分析一下咧栗,超類(Any)是所有類的父類,而分類中所有元素都有open修飾符虱肄,如果我們跟Any的語法去寫一個類致板,是不是就是一個繼承類了,說明浩峡,open修飾符是我們定義繼承類的修飾符

4.2 定義

4.2.1 基礎使用
  • 定義繼承類的關鍵字為:open可岂。不管是類错敢、還是成員都需要使用open關鍵字翰灾。
  • 定義格式為:
open class 類名{
    open var/val 屬性名 = 屬性值
    open fun 函數名()
}

eg:

open class InheritClass{
    open var num = 3
    open fun funOne() = "funOne"
    open fun funTwo() = 25
}

class DemoTest : InheritClass(){
    // 這里值得注意的是:Kotlin使用繼承是使用`:`符號,而Java是使用extends關鍵字
}

fun main(args:Array<String>){
    val demoTest = DemoTest()
    println(demoTest.num)
    println(demoTest.funOne())
    println(demoTest.funTwo())
}

result:

3
funOne
25

說明:
從上面的代碼可以看出稚茅,DemoTest類只是繼承了Demo類纸淮,并沒有實現任何的代碼結構。一樣可以使用Demo類中的屬性與函數亚享。這就是繼承的好處咽块。

4.2.2 構造函數

在上次的分享中有提到過,在kotlin中欺税,可以有一個主構造函數侈沪,或者多個輔助函數⊥碓洌或者沒有構造函數的情況亭罪。

在這里,來說一下實現類無主構造函數歼秽,和存在主構造函數的情況应役。

  • 無主構造函數

當實現類無主構造函數時,則每個輔助構造函數必須使用super關鍵字初始化基類型,或者委托給另一個構造函數箩祥。 請注意院崇,在這種情況下,不同的輔助構造函數可以調用基類型的不同構造函數

這里用view的自定義來說明一下袍祖,eg:

class MyView : View(){

    constructor(context: Context) : super(context)

    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int)
        : super(context, attrs, defStyleAttr)
}

可以看出底瓣,當實現類無主構造函數時,分別使用了super()去實現了基類的三個構造函數蕉陋。

  • 存在主構造函數

當存在主構造函數時濒持,主構造函數一般實現基類型中參數最多的構造函數,參數少的構造函數則用this關鍵字引用即可了寺滚。這點在Kotlin——中級篇(一):類(class)詳解這篇文章是講解到的柑营。

這里同樣用view自定義的例子,eg:

class MyView(context: Context?, attrs: AttributeSet?, defStyleAttr: Int)
    : View(context, attrs, defStyleAttr) {

    constructor(context: Context?) : this(context,null,0)
    
    constructor(context: Context?,attrs: AttributeSet?) : this(context,attrs,0)
}
4.2.3 函數的重載和重寫

kotlin的重載和重寫的理解和Java一樣村视,重載:是在一個類里面官套,方法名字相同,而參數不同蚁孔。返回類型可以相同也可以不同奶赔;重寫是子類對父類的允許訪問的方法的實現過程進行重新編寫,返回值和形參都不能改變。即外殼不變杠氢,核心重寫站刑!

4.2.3.1 重寫函數中的兩點特殊用法

這里介紹兩點kotlin相較于Java特殊的地方

  • 當基類中的函數,沒有用open修飾符修飾的時候鼻百,實現類中出現的函數的函數名不能與基類中沒有用open修飾符修飾的函數的函數名相同绞旅,不管實現類中的該函數有無override修飾符修飾。

eg:

open class InheritClass{
    fun test(){}
}

class DemoTest : InheritClass(){
    // 這里聲明一個和基類型無open修飾符修飾的函數温艇,且函數名一致的函數
    // fun test(){}   編輯器直接報紅因悲,根本無法運行程序
    // override fun test(){}   同樣報紅
}
  • 當一個類不是用open修飾符修飾時,這個類默認是final的
4.2.3.1 方法重載

方法重載也是體現了面向對象中的多態(tài)的特性
方法重載在繼承類同樣有效
eg:

open class InheritClass{
    open fun funThree() = "funThree"
}

class DemoTest : InheritClass(){
    fun funThree(name:String):String{
        return name
    }
    override fun funThree(): String {
        return super.funThree()
    }
}

fun main(args:Array<String>){
    val demoTest = DemoTest()
    println(demoTest.funThree())
    demoTest.funThree("I am funThree,Do you known polymorphic?")
}

result:

funThree
I am funThree,Do you known polymorphic?
4.2.4 重寫屬性
  • 重寫屬性和重寫方法其實大致是相同的勺爱,但是屬性不能被重載晃琳。
  • 重寫屬性即指:在基類中聲明的屬性,然后在其基類的實現類中重寫該屬性琐鲁,該屬性必須以override關鍵字修飾卫旱,并且其屬性具有和基類中屬性一樣的類型。且可以重寫該屬性的值(Getter)

eg:

open class InheritClass{
    open var num = 3
}

class DemoTest : InheritClass(){
    override var num: Int = 10
}

fun main(args:Array<String>){
    val demoTest = DemoTest()
    println(demoTest.num)
}

result:

10
4.2.4.1 重寫屬性中围段,val與var的區(qū)別

有一點值得我們注意的是當基類中屬性的變量修飾符為val的使用顾翼,其實現類可以用重寫屬性可以用var去修飾。反之則不能蒜撮。
eg:

open class InheritClass {
    open val valStrOne = "I am val string one"
    open val valStrTwo = "I am val string two"
    open val valStrThree = "I am val string three"
    open val valStrFour = "I am val string four"
}

class DemoTest : InheritClass() {
    override val valStrOne: String
        get() = super.valStrOne

    override var valStrTwo: String = ""
        get() = super.valStrTwo

    override val valStrThree: String = ""

    override var valStrFour: String = "abc"
        set(value){field = value}
}

fun main(args: Array<String>) {
    val demoTest = DemoTest()
    println(demoTest.valStrOne)
    println(demoTest.valStrTwo)
    println(demoTest.valStrThree)
    println(demoTest.valStrFour)
    demoTest.valStrFour = "I am Icon man"
    println(demoTest.valStrFour)
}

result:

I am val string one
I am val string two
I am val string three
I am val string four
I am Icon man
4.2.4.2暴构、Getter()函數慎用super關鍵字

在這里值得注意的是跪呈,在實際的項目中在重寫屬性的時候不用get() = super.xxx,因為這樣的話,不管你是否重新為該屬性賦了新值取逾,還是支持setter(),在使用的時候都調用的是基類中的屬性值耗绿。

eg:

open class InheritClass {
    open val valStrFive = "I am val string five"
}

class DemoTest : InheritClass() {
    override var valStrFive: String = "cba"
        get() = super.valStrFive
        set(value){field = value}
}

fun main(args: Array<String>) {
    val demoTest = DemoTest()
    println(demoTest.valStrFive)
    demoTest.valStrFive
    println(demoTest.valStrFive)
}

result:

I am val string five
I am val string five
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市砾隅,隨后出現的幾起案子误阻,更是在濱河造成了極大的恐慌,老刑警劉巖晴埂,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件究反,死亡現場離奇詭異,居然都是意外死亡儒洛,警方通過查閱死者的電腦和手機精耐,發(fā)現死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來琅锻,“玉大人卦停,你說我怎么就攤上這事∧张睿” “怎么了惊完?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長处硬。 經常有香客問我小槐,道長,這世上最難降的妖魔是什么荷辕? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任凿跳,我火速辦了婚禮,結果婚禮上桐腌,老公的妹妹穿的比我還像新娘拄显。我一直安慰自己苟径,他們只是感情好案站,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著棘街,像睡著了一般蟆盐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上遭殉,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天石挂,我揣著相機與錄音,去河邊找鬼险污。 笑死痹愚,一個胖子當著我的面吹牛富岳,可吹牛的內容都是我干的。 我是一名探鬼主播拯腮,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼窖式,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了动壤?” 一聲冷哼從身側響起萝喘,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎琼懊,沒想到半個月后阁簸,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡哼丈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年启妹,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片醉旦。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡翅溺,死狀恐怖,靈堂內的尸體忽然破棺而出髓抑,到底是詐尸還是另有隱情咙崎,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布吨拍,位于F島的核電站褪猛,受9級特大地震影響,放射性物質發(fā)生泄漏羹饰。R本人自食惡果不足惜伊滋,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望队秩。 院中可真熱鬧笑旺,春花似錦、人聲如沸馍资。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鸟蟹。三九已至乌妙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間建钥,已是汗流浹背藤韵。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留熊经,地道東北人泽艘。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓欲险,卻偏偏與公主長得像,于是被迫代替她去往敵國和親匹涮。 傳聞我的和親對象是個殘疾皇子盯荤,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內容