如何在Scala中处理POJO / JavaBean模式?

时间:2012-03-12 19:05:23

标签: scala

就像问题一样。 scala是否像Java一样推广它?或者它已经演变成Scala的更惯用语?或者说它变得无关紧要了?

POJOs和JavaBeans意思是:

  1. 不带参数的构造函数
  2. 属性是私有的,getter和setter是公共的
  3. getters和setter定义属性,隐藏属性

  4. 此外,Scala对使用与此问题相关的旧publicprivateprotected属性设计有意见(抱歉,我不喜欢使用此术语)吗?

1 个答案:

答案 0 :(得分:37)

Scala也有类似POJO的习语,但它们与JavaBeans不同,Scala强调不同方面。

  1. Scala有不同的命名约定:

    def foo: Foo        //Foo getFoo() in Java
    def foo_=(foo: Foo)  //void setFoo(Foo foo) in Java
    

    这样,即使您决定从getter / setter切换到直接字段访问,也可以写obj.fooobj.foo = bar,反之亦然。这称为统一访问原则

  2. 由于Java互操作性,引入了@BeanProperty注释:

    @BeanProperty var foo: Foo = _
    

    上面的代码不仅创建了类似Scala的getter / setter,而且还创建了类似Java的代码,因此所有Java框架都可以无缝地工作。

  3. Scala强迫您在变量(var)和值(val)之间做出决定,因此您发现自己经常使用不可变对象

  4. 我真的更喜欢构造函数中的不可变对象和初始化,这在Scala中非常简单:

    class Foo(val age: Int, val name: String)
    

    val类默认情况下case

    case class Foo(age: Int, name: String)
    

    这段代码简洁明了。但是,如果您需要与Java框架合作,您仍然需要no-argu构造函数和setter:

    public class Foo(var age: Int, var name: String) {
    
        def this() {
            this(0, "")
        }
    
    }
    

    注意val替换为var

  5. 与Java相比,Scala中的访问修饰符具有稍好的默认值:

    class Foo(var a: Int, x: Int) {
    
        var b: Int = _
    
        private var c: Int = _
    
        private[this] var d: Int = _
    
        def twisted = a + b + c + d + x
    
    }
    

    变量ab将成为private字段,其中包含public个getter / setter(默认情况下字段为私有,方法为公共字段)。 cd也是私有变量。但额外的private[this]使得d可以直接在课堂内部访问,而不是私有的getter / setter。

    因为x在构造函数旁边的某处使用,所以Scala也会自动为它创建私有字段。但是,不会生成任何getter / setter,可以使用twisted方法直接访问它(与d相同)。

  6. 更新:在评论中,您要求重命名getter / setter。这是更复杂的例子。 Getters / setter同时根据两个字段计算值:

    class Foo {
    
        private[this] var first: Char = _
        private[this] var rest: String = _
    
        def fake = first + rest
    
        def fake_=(s: String) {
            first = s.head
            rest = s.tail
        }
    
    }
    

    内部看起来很复杂,但从外面看起来它看起来很古老:

    val foo = new Foo()
    foo.fake = "ABC"
    println(foo.fake)
    

    就像是:

    class Foo(var fake: String)