09_Scala_OOP下_静态_伴生类_对象_嵌套类_投影屏蔽
Java中静态方法不通过对象调用,通过类对象调用,所以静态操作并不是面向对象
public class Alex_Static {
public static void main(String[] args) {
Alex.sayAlex();
}}
//public static 返回值类型 方法名(参数列表) {方法体}
class Alex {
public static void sayAlex(){
System.out.println("sayAlex");
}
}
Scala中静态的概念-伴生对象
Scala 无静态的概念, 使用伴生对象兼容Java 静态的概念,类的所有静态内容都在它的伴生对象中声明和调用
静态属性和静态方法
1 伴生对象采用object关键字声明,伴生对象中声明的全是 "逻辑静态"内容,可以通过伴生对象名称直接调用。
2 伴生对象对应的类称之为伴生类,伴生对象名称应该和伴生类名一致。
3 伴生对象中的属性和方法都可以通过伴生对象名(类名)直接调用访问
4 逻辑的理解,伴生对象其实就是类的静态方法和成员的集合 (逻辑静态方法)
5 实际,scala并没有生成静态的内容,只不过是将伴生对象生成了一个新的类,实现属性和方法的调用。
6 底层,伴生对象实现静态特性是依赖于 public static final MODULE$ 实现的。
7 伴生对象的声明应该和伴生类的声明在同一个源码文件中(如果不在同一个文件中会运行错误!)
8 如果 class A 独立存在,那么A就是一个类, 如果 object A 独立存在,那么A就是一个"静态"性质的对象[即类对象], 在 object A中声明的属性和方法可以通过 A.属性 和 A.方法 来实现调用
9 存在伴生类和伴生对象时,图标
object CountGame {
def main(args: Array[String]): Unit = {
val f1 = new Fish("white")
val f2 = new Fish("black")
val f3 = new Fish("golden")
Fish.count_fish(f1)
Fish.count_fish(f2)
Fish.count_fish(f3)
Fish.show_count()
}
}
//说明
//1. 当在同一个文件中,有 class Fish 和 object Fish
//2. class Fish 称为伴生类,将非静态的内容写到该类中
//3. object Fish 称为伴生对象,将静态的内容写入到该对象(类)
//4. class Fish 编译后底层生成 Fish类 Fish.class
//5. object Fish 编译后底层生成 Fish$类 Fish$.class
//6. 对于伴生对象的内容,我们可以直接通过 Fish.属性 或者方法
//伴生类
class Fish(fname: String) {
var name: String = fname
}
//伴生对象
object Fish {
var total_sum: Int = 0
def count_fish (f: Fish): Unit ={
total_sum += 1
}
def show_count ():Unit ={println("总数鱼: " + total_sum)}
}
底层原理
伴生对象-apply方法
在伴生对象中定义apply方法,可以实现: 类名(参数) 方式 来创建对象实例
object ApplyDemo01 {
def main(args: Array[String]): Unit = {
val dog1 = new Dog("姐夫")
//在伴生对象中定义apply方法,可以实现: 类名(参数) 方式 来创建对象实例
//使用apply方法来创建对象
val dog2 = Dog("小姐夫") //自动 apply(pName: String)
val dog3 = Dog() // 自动触发 apply()
println("Dog2.name=" + dog2.name) //小姐夫
println("Dog3.name=" + dog3.name) //匿名大姐夫
}
}
//案例演示apply方法.
class Dog (pName:String) {
var name: String = pName
}
object Dog {
//编写一个apply
def apply(pName: String): Dog = new Dog(pName)
def apply(): Dog = new Dog("匿名大姐夫")
}
Java中,类中五大成员: 属性 方法 构造器 内部类 代码块
Java 内部类 可以直接访问私有属性,并且可以体现类与类之间的包含关系
public class TestJava {
public static void main(String[] args) {
//Java内部类的分类
// 从定义在外部类的成员位置上来看,
// 1) 成员内部类(没用static修饰)
// 2) 静态内部类(使用static修饰)
//创建一个外部类对象
OuterClass outer1 = new OuterClass();
//创建一个外部类对象
OuterClass outer2 = new OuterClass();
// 创建Java成员内部类
// 说明在Java中,将成员内部类当做一个属性,因此使用下面的方式来创建 outer1.new InnerClass().
OuterClass.InnerClass inner1 = outer1.new InnerClass();
OuterClass.InnerClass inner2 = outer2.new InnerClass();
//下面的方法调用说明在java中,内部类只和类型相关,也就是说,只要是
//OuterClass.InnerClass 类型的对象就可以传给 形参 InnerClass ic
inner1.test(inner2);
inner2.test(inner1);
// 创建Java静态内部类
// 因为在java中静态内部类是和类相关的,使用 new OuterClass.StaticInnerClass()
OuterClass.StaticInnerClass staticInner = new OuterClass.StaticInnerClass();
}
}
class OuterClass { //外部类
class InnerClass { //成员内部类
public void test(InnerClass ic) {
System.out.println(ic);
}
}
static class StaticInnerClass { //静态内部类
}
}
Scala中嵌套类 等价于 Java中的内部类
Scala嵌套类 的成员内部类和静态内部类
在内部类中访问外部类的属性
通过外部类对象访问 :外部类名.this.属性名
通过外部类别名访问(推荐) :外部类名别名.属性名
类型投影 作用:屏蔽外部对象对内部类对象的限制/影响
object AlexIOuterClassDemo {
def main(args: Array[String]): Unit = {
val outer1: AlexOuterClass = new AlexOuterClass();
val outer2: AlexOuterClass = new AlexOuterClass();
//在scala中,创建成员内部类的语法是
//对象.内部类 的方式创建, 这里语法可以看出在scala中,默认情况下内部类实例和外部对象关联
// outer1 outer2创建出来的内部类不是同一个类型
val inner1 = new outer1.AlexInnerClass
val inner2 = new outer2.AlexInnerClass
//测试一下使用inner1 去调用 info()
inner1.info()
//在默认情况下,scala的内部类的实例和创建该内部类实例的外部对象关联.
inner1.test_ori(inner1) // 必须是 inner1 outer1.AlexInnerClass
inner2.test_ori(inner2) // 必须是 inner2 outer1.AlexInnerClass
// 使用投影后 忽略了外部对象对内部对象的限制 AlexOuterClass#AlexInnerClass
inner1.test(inner2)
inner2.test(inner1)
//创建静态内部类实例 通Java创建方式
val staticInner = new AlexOuterClass.ScalaStaticInnerClass()
}
}
//外部类 问外部类的属性的方法1 外部类名.this.属性
class AlexOuterClass {
//定义两个属性
var name = "alex"
private var age = 35 // 私有属性
class AlexInnerClass { //成员内部类,
def info() = {
// 方式1 :外部类访问外部类的属性: 使用外部类名.this.属性名
// AlexOuterClass.this 就相当于是 AlexOuterClass 这个外部类的一个实例,
// 通过 AlexOuterClass.this 实例对象去访问 name 属性, 同时也可以访问 私有属性 age
println("name = " + AlexOuterClass.this.name + " sal =" + AlexOuterClass.this.age) }
//如果使用 外部类#内部类 表示忽略内部类的对象关系,等同于Java中内部类的语法操作
//这里有一个方法,可以接受AlexIuterClass实例
//下面的 AlexOuterClass#AlexIuterClass 类型投影的作用就是屏蔽 外部对象对内部类对象的限制/影响
def test(obj: AlexOuterClass#AlexInnerClass): Unit = {
println("使用了类型投影" + obj)
}
def test_ori(obj: AlexInnerClass): Unit = {
println("不使用了类型投影 会锁定外部对象" + obj)
}
}}
//方式2 :外部类访问外部类的属性 使用别名的方式
//1. 将外部类属性,写在别名后面
class SullyOuterClass {
sullyouter => //这里我们可以这里理解 外部类的别名 看做是外部类的一个实例
//定义两个属性
var name = "alex"
private var age = 35
class SullyIuterClass { //成员内部类,
def info() = {
// 访问方式:外部类别名.属性名
println("name~ = " + sullyouter.name + " sal~ =" + sullyouter.age) }
}}
object AlexOuterClass { //伴生对象
class ScalaStaticInnerClass { //静态内部类
}}
- 点赞
- 收藏
- 关注作者
评论(0)