/**对象表达式：obj:xxx{ .....  },匿名类的对象，在函数内部定义或用private修饰的可直接使用，并可以访问或修改其作用域内的局部变量
 * 对象声明:object xxx:yyy{......},模拟单例（用名称直接访问），不能定义在函数内部
 * 伴生对象：companion object xxx:yyy{......},模拟静态类（名称xxx可省略，此时可用Companion代替），只能在类中定义，并且每个类只能存在一个，用外层类名直接访问其中的元素
 */
interface Outputable{
    fun output(msg: String)
}
abstract class Product(var price: Double){
    abstract val name: String
    abstract fun printInfo()
}
private var objx = object { var name = "Java"}

//对象声明：初始化快、属性、方法、嵌套类
 object MyObject1 {
    // 初始化块
    init{
        println("初始化块")
    }
    // 属性
    var name = "Kotlin"
    // 方法
    fun test(){
        println("test方法")
    }
    // 只能包含嵌套类，不能包含内部类
    class Foo
}

//对象声明：
object MyObject2: Outputable, Product(28.8){
    override fun output(msg: String){
        println("输出信息：" + msg)
    }
    override val name: String
        get() = "激光打印机"
    override fun printInfo(){
        println("高速激光打印机，支持自动双面打印！")
    }
}

//使用companion修饰的伴生对象
class OutClass{
     val attr = "外部属性值"
    // 使用companion修饰的伴生对象
    companion object MyObject: Outputable{
        val name = "name属性值"
        //println(attr)<- Error!   不能访问外部属性
        // 重写父接口中的抽象方法
        override fun output(msg: String){
            for(i in 1..6){
                println("<h${i}>${msg}</h${i}>")
            }
        }
    }
}

// 为伴生对象扩展方法
fun OutClass.MyObject.test(){
    println("为伴生对象扩展的方法")
}
val OutClass.MyObject.foo
    get() = "为伴生对象扩展的属性"

fun main() {
    //对象表达式成员：初始化快、属性、方法、内部类
    var obj1 = object {
        // 初始化块
        init{
            println("初始化块")
        }
        // 属性
        var name = "Kotlin"
        // 方法
        fun test(){
            println("test方法")
        }
        // 只能包含内部类，不能包含嵌套类
        inner class Foo
    }
    println(objx.name)
    println(MyObject1.name)
    obj1.test()
    MyObject1.test()

    // 指定2个父类型的对象表达式,由于Product只有一个带参数的构造器，因此需要传入构造器参数
    var obj2 = object: Outputable, Product(28.8){
        override fun output(msg: String){
            println("输出信息：" + msg)
        }
        override val name: String
            get() = "激光打印机"
        override fun printInfo(){
            println("高速激光打印机，支持自动双面打印！")
        }
    }
    println(obj2.name)
    println(MyObject2.name)
    obj2.output("Kotlin真不错！")
    MyObject2.output("Java也不错")
    obj2.printInfo()
    MyObject2.printInfo()

    println(objx.name)

    // 使用伴生对象所在的类调用伴生对象的成员
    OutClass.output("xotty.org")
    println(OutClass.name)
    // 通过伴生对象所在的类调用为伴生对象扩展的成员
    OutClass.test()
    println(OutClass.foo)
}



