加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

惯用的Scala方法来处理基础与派生类字段名称?

发布时间:2020-12-16 19:00:42 所属栏目:安全 来源:网络整理
导读:考虑 Scala中的以下基类和派生类: abstract class Base( val x : String ) final class Derived( x : String ) extends Base( "Base's " + x ) { override def toString = x } 这里,派生类参数的标识符“x”会覆盖Base类的字段,因此可以像这样调用toString
考虑 Scala中的以下基类和派生类:

abstract class Base( val x : String )

    final class Derived( x : String ) extends Base( "Base's " + x )
    {
        override def toString = x
    }

这里,派生类参数的标识符“x”会覆盖Base类的字段,因此可以像这样调用toString:

println( new Derived( "string" ).toString )

返回Derived值,并给出结果“string”.

因此,对’x’参数的引用会提示编译器自动生成Derived的一个字段,该字段在调用toString时提供.这通常是非常方便的,但是会导致字段的复制(我现在将字段存储在Base和Derived上),这可能是不合需要的.为了避免这种复制,我可以将Derived类参数从’x’重命名为别的东西,如’_x’:

abstract class Base( val x : String )

    final class Derived( _x : String ) extends Base( "Base's " + _x )
    {
        override def toString = x
    }

现在调用toString返回“Base的字符串”,这就是我想要的.不幸的是,代码现在看起来有点丑陋,使用命名参数来初始化类也变得不那么优雅:

new Derived( _x = "string" )

还有一个风险是忘记给派生类的初始化参数不同的名称,并且无意中引用了错误的字段(不希望的,因为Base类可能实际上具有不同的值).

有没有更好的办法?

编辑1:要澄清,我真的只想要Base值;对于初始化基类的字段,派生类似乎是必需的.这个例子只是引用他们来说明随后的问题.

编辑2:实际上,如果我使用var而不是vals,那么这个例子会更加清晰,因为这突出了在基类中稍后改变的值的问题:

class Base( var x : Int ) { def increment() { x = x + 1 } }
    class Derived( x : Int ) extends Base( x ) { override def toString = x.toString }

    val derived = new Derived( 1 )
    println( derived.toString )     // yields '1',as expected
    derived.increment()
    println( derived.toString )     // still '1',probably unexpected

编辑3:如果派生类最终隐藏基类字段,可能会有一种方法来抑制自动字段生成.看起来Scala编译器实际上可能是为你设计的,但这当然违背了更为一般的规则,即更接近的标识符(派生类“x”)隐藏更多远程标识符(Base类“ ‘X’).似乎一个相当不错的解决方案将是一个修饰符,如“noval”,也许就像这样:

class Base( var x : Int ) { def increment() { x = x + 1 } }
    class Derived( noval x : Int ) extends Base( x ) { override def toString = x.toString }

    val derived = new Derived( 1 )
    println( derived.toString )     // yields '1',as expected
    derived.increment()
    println( derived.toString )     // still '2',as expected

解决方法

避免复制字段的惯用方式是写

abstract class Base { val x: String }

final class Derived(val x: String) extends Base {
   def toString = x
}

但是,在您的版本中,您确实需要第二个字段,因为您有两个不同的值.正确地指出,给这些字段的名字相同可能会导致混乱.

既然你实际上并不需要在构造函数之外的构造函数参数,你可以使用这种方法(一个私有的构造函数和一个作为工厂的伴随模块):

abstract class Base { val x: String }

final class Derived private (val x: String) extends Base {
   def toString = x
}
object Derived {
   def apply(x: String) = new Derived("Base " + x)
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读