Intro
在Scala中,你几乎可以在任何语法结构中内嵌任何语法结构。如在类中可以再定义一个类,这样的类是嵌套类,其他语法结构也是一样。基本语法如下:
class ScalaOuterClass { // 外部类
class ScalaInnerClass { //成员内部类
}
}
object ScalaOuterClass { //伴生对象
class ScalaStaticInnerClass { //静态内部类
}
}
那么如何创建内部类对象呢?看个Demo:
class ScalaOuterClass {
class ScalaInnerClass { //成员内部类
}
}
object ScalaOuterClass { //伴生对象
class ScalaStaticInnerClass { //静态内部类
}
}
// 创建外部类
val outer1 : ScalaOuterClass = new ScalaOuterClass()
val outer2 : ScalaOuterClass = new ScalaOuterClass()
// 创建内部类
val inner1 = new outer1.ScalaInnerClass()
val inner2 = new outer2.ScalaInnerClass()
//创建静态内部类对象
val staticInner = new ScalaOuterClass.ScalaStaticInnerClass()
defined class ScalaOuterClass
defined object ScalaOuterClass
outer1: ScalaOuterClass = ScalaOuterClass@39f042fd
outer2: ScalaOuterClass = ScalaOuterClass@73523062
inner1: outer1.ScalaInnerClass = ScalaOuterClass$ScalaInnerClass@39bd005f
inner2: outer2.ScalaInnerClass = ScalaOuterClass$ScalaInnerClass@278ec3a
staticInner: ScalaOuterClass.ScalaStaticInnerClass = ScalaOuterClass$ScalaStaticInnerClass@3924b122
内部类访问外部类属性
内部类访问外部类的属性有两种方式,先看第一种:
class ScalaOuterClass {
val name="Jack"
private val age = 19
class ScalaInnerClass { //成员内部类
def showMe(){
printf("My name is %s.I am %d years old.",ScalaOuterClass.this.name,ScalaOuterClass.this.age)
}
}
}
val outer1 : ScalaOuterClass = new ScalaOuterClass()
val inner1 = new outer1.ScalaInnerClass()
inner1.showMe()
My name is Jack.I am 19 years old.
defined class ScalaOuterClass
outer1: ScalaOuterClass = ScalaOuterClass@494c9bb3
inner1: outer1.ScalaInnerClass = ScalaOuterClass$ScalaInnerClass@533ec21e
warning: previously defined object ScalaOuterClass is not a companion to class ScalaOuterClass.
Companions must be defined together; you may wish to use :paste mode for this.
第一种方式是在内部类中,通过外部类名.this.属性名的方式调用。还可以外部类名别名.属性名的方式调用。看个Demo:
class ScalaOuterClass {
myOuter =>
val name="Jack"
private val age = 19
class ScalaInnerClass { //成员内部类
def showMe(){
printf("My name is %s.I am %d years old.",myOuter.name,myOuter.age)
}
}
}
val outer1 : ScalaOuterClass = new ScalaOuterClass()
val inner1 = new outer1.ScalaInnerClass()
inner1.showMe()
My name is Jack.I am 19 years old.
defined class ScalaOuterClass
outer1: ScalaOuterClass = ScalaOuterClass@104fdadf
inner1: outer1.ScalaInnerClass = ScalaOuterClass$ScalaInnerClass@42d4fa08
warning: previously defined object ScalaOuterClass is not a companion to class ScalaOuterClass.
Companions must be defined together; you may wish to use :paste mode for this.
类型投影
当我们新建一个内部类的对象时,会先和外部类的实例对象绑定,此时每个不同的内部类对象所属类不完全相同(粗暴的这么理解吧,因为他们对应外部类对象都不一样)。先看个Demo:
class ScalaOuterClass3 {
myOuter =>
class ScalaInnerClass3 { //成员内部类
def test(ic: ScalaInnerClass3): Unit = {
System.out.println(ic)
}
}
}
val outer1 : ScalaOuterClass3 = new ScalaOuterClass3()
val outer2 : ScalaOuterClass3 = new ScalaOuterClass3()
val inner1 = new outer1.ScalaInnerClass3()
val inner2 = new outer2.ScalaInnerClass3()
inner1.test(inner1) // ok, 因为 需要outer1.ScalanInner
inner1.test(inner2) // error, 需要outer1.ScalanInner而实际是outer2.ScalanInner
只需要做一个简单的修改,就可以做所谓的类型投影ic: ScalaOuterClass3#ScalaInnerClass3
class ScalaOuterClass3 {
myOuter =>
class ScalaInnerClass3 { //成员内部类
def test(ic: ScalaOuterClass3#ScalaInnerClass3): Unit = {
System.out.println(ic)
}
}
}
val outer1 : ScalaOuterClass3 = new ScalaOuterClass3()
val outer2 : ScalaOuterClass3 = new ScalaOuterClass3()
val inner1 = new outer1.ScalaInnerClass3()
val inner2 = new outer2.ScalaInnerClass3()
inner1.test(inner1)
inner1.test(inner2)
$line27.$read$$iw$$iw$ScalaOuterClass3$ScalaInnerClass3@6f32ac74
$line27.$read$$iw$$iw$ScalaOuterClass3$ScalaInnerClass3@50973861
defined class ScalaOuterClass3
outer1: ScalaOuterClass3 = ScalaOuterClass3@1eef5be9
outer2: ScalaOuterClass3 = ScalaOuterClass3@23e0008c
inner1: outer1.ScalaInnerClass3 = ScalaOuterClass3$ScalaInnerClass3@6f32ac74
inner2: outer2.ScalaInnerClass3 = ScalaOuterClass3$ScalaInnerClass3@50973861
2020-03-08 于南京市栖霞区