Scala编程——第九章:面向对象编程(高级部分)—— Scala静态概念

本文深入探讨Scala的静态概念,包括单例对象、伴生对象、apply方法及其应用。单例对象作为Scala中的静态替代,伴生对象能访问彼此的私有成员,apply方法用于简洁地创建对象,而孤立对象常用于应用程序的入口或工具方法的集合。
摘要由CSDN通过智能技术生成

面向对象编程(高级部分)—— Scala静态概念(1)


面向对象编程高级部分,主要学习Scala中一下四个知识点

  • 1.静态概念
  • 2.继承(链接:继承)
  • 3.特质(链接:特质)
  • 4.包(链接:

一、静态概念

1.单例对象

  • Scala比Java 更具有面向对象的特点,Scala的类不允许有静态( static )成员
  • Scala虽然没有静态方法或者静态字段。对此类使用场景, Scala提供Object语法(单例对象)来达到相同的目的
  • 单例对象(singleton object) de 定义看上去和类相似,使用object 关键字替换class 。单例对象定义了某个类的单例对象,其中包含了你想要的特性,例如
    //定义一个单例对象。
    Object Account{
    	private var LastNumber = 0 
    	def newUniqeNumber() = {
    		lastNumber += 1
    		lastNumber
    	}
    }
    //调用单例对象中的方法
    Account.newUniqeNumber() //创建一个唯一的新的账号。
    
  • 单例对象本质上可以拥有类的所有特性,除了不能提供构造器参数。
  • 对于任何在java中使用单例对象的地方,Scala也都可以使使用单例对象实现:
    • 作为存放工具函数或者常量的地方。
    • 高效的共享单个不可变实例。
    • 需要使用某个单例实例来协调某个服务时(参考单例模式)。

2.伴生对象

当单例对象跟某个类共用一个名字时,它被称作这个类的伴生对象(companion object)。

  • 必须在同一个源码文件中定义类和类的伴生对象,同时类叫做这个单例对象的伴生类
  • 伴生类和伴生对象可以互相访问对方的私有成员。伴生类可以接受参数,而伴生对象不可以,因为你没法用new实例化单例对象,也就没有任何手段向它传参
  • 每个单例对象都是通过一个静态变量引用合成类的实例来实现的,因此单例对象的从初始化的语义上根Java的静态成员是一致的,尤其体现在单例对象在有代码首次访问时才被初始化
    class Account{//伴生类
       val id = Account.newUniqueNumber()
       private var balance = 0.0
       def deposit(amount: Double) = { balance += amount}
    }
    
    object Account{//伴生对象
       private var  lastNumber = 0
       def newUniquieNumber() = {
       		lastNumber += 1
       		lastNumber
       }
    }
    
    注意:伴生对象的成员 并不在伴生类的作用域内。Account 类必须通过类名.方法名() 方式调用
     例如:应该是Account.newUniqueNumber()调用,而不是直接newUniqueNumber()来调用伴生对象的方法。
    
    java反编译的代码(在线反编译http://www.javadecompilers.com/):
    class Account半生类 反编译后底层对应Acouunt类 和Acouunt.class源文件
    public class Account
    {
        private final int id;
        private double balance;
        
        public static int newUniqueNumber() {
            return Account$.MODULE$.newUniqueNumber();//重点关注
        }
        
        public int id() {
            return this.id;
        }
        
        private double balance() {
            return this.balance;
        }
        
        private void balance_$eq(final double x$1) {
            this.balance = x$1;
        }
        
        public void deposit(final double amount) {
            this.balance_$eq(this.balance() + amount);
        }
        
        public Account() {
            this.id = Account$.MODULE$.newUniqueNumber();
            this.balance = 0.0;
        }
    }
    
    object Account伴生对象反编译后对应 Account$类“和 Account$.class源文件
    public final class Account$
    {
        public static Account$ MODULE$;
        private int lastNumber;
        
        static {
            new Account$();
        }
        
        private int lastNumber() {
            return this.lastNumber;
        }
        
        private void lastNumber_$eq(final int x$1) {
            this.lastNumber = x$1;
        }
        
        public int newUniqueNumber() {
            this.lastNumber_$eq(this.lastNumber() + 1);
            return this.lastNumber();
        }
        
        private Account$() {
            Account$.MODULE$ = this;
            this.lastNumber = 0;
        }
    }
    
    从源码不难看出,伴生类中val id = Account.newUniqueNumber() 这一行代码,实际上是分成了三步:
    在这里插入图片描述
    ①:伴生类首先生成了一个和伴生对象中的同名方法public static int newUniqueNumber() 。
    ②:伴生对象底层生成了一个静态的 Accoun$类型的 MODULE$静态对象
    ③:伴生类的newUniqueNumber() 方法 返回一个通过 MODULE$静态对象调用伴生对象的同名newUniqueNumber()方法。
    同过上述过程了,实现了静态方法的调用。其中最最重要的是,伴生对象实现静态特性是依赖于
    public static Account$ MODULE$ 这个静态对象实现的。伴生类通过MODULE$调用伴生对象的方法。

3.apply方法

我们通常会定义和使用对象的apply方法。可以通过:类名(参数1,…,参数N)方式创建对象。

  • 类名(参数1,…,参数N) 这种形式会调用伴生对象的apply方法返回的是一个伴生类的对象。例如
    Array(1,2,3) //调用了Array的apply方法。
    
    再来看看Array的源码
    
    object Array extends FallbackArrayBuilding {
    	def apply[T: ClassTag](xs: T*): Array[T] = {...}
    	...//内部定义了很多的apply方法
    	def apply(x: Unit, xs: Unit*): Array[Unit] = {...}
    }
    
  • 定义apply方法的实例:
    class Account private(val id: Int, initialbalance: Double){
    	private var balance = initialBalance
    		...
    }
    object Account{
    	def apply(initalBalance: Double) = {
    		new Account(newUniqueNumber(),initialBalance)
    	}
    	...
    }
    
    这样就可以这样来构建账号了:
    val acct = Acount(100)

4.应用程序的对象

没有同名的伴生类的单例对象又被 称为孤立对象(standalone object)。孤立对象有很多种用途,包括将工具方法归集在一起,或定义 Scala 应用程序的入口。例如:

object Hello{
	def main(args: Array[String]){
		println("Hello,Scala")
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值