【问题标题】:Difference between protected and protected[this]受保护和受保护之间的区别[this]
【发布时间】:2016-08-22 19:43:03
【问题描述】:

我有以下代码:

class Base{
    protected val alpha ="Alpha";
    protected def sayHello = "Hello";
}
class Derived extends Base{
        val base = new Base;
        def hello = println(this.alpha +" "+this.sayHello) ;
       // def hello = println(base.alpha +" "+base.sayHello) ; // don't compile
    }

    object MyObj extends App{
            val x=new Derived;
            x.hello;
        }

在Base 类中,如果我将protected 标记为this,则代码按预期工作;如果我不使用this 标记它,一切都会按预期进行。

protected 和 protected[this] 在 Scala 中是否等效?如果是,为什么 Scala 会同时提供这两者?如果不是,它们有何不同?

【问题讨论】:

    标签: scala this protected


    【解决方案1】:

    Scala protected 和它的兄弟protected[this] ,protected[pkg] 有点压倒性,但是我发现使用protected 的Java 哲学很容易记住解决方案。 1st 如何在 Java 中看到受保护的成员

    1. 它们对子类可见(子类可能在同一个包或其他包中)
    2. 它们对于与指定受保护成员的类在同一包中的任何类都是可见的。

    显然它们对类本身是可见的。

    但是 Scala 对它们如何对子类可见有一些限制。默认情况下,它们只对子类可见。它们对于声明哪个类的包是不可见的。但是存在两种情况,它们在子类中是如何可见的。

    如果受保护的成员不合格(纯受保护),那么它在 另一个声明类的实例 到声明类以及 this 到类和子类中可见,例如强>

    class Base{
        protected val alpha ="Alpha";
        protected def sayHello = "Hello";
    }
    class Derived extends Base{
            def hello = println((new Derived()).sayHello) ;
            def hello2 = println(this.sayHello);
    
    }
    

    如果受保护的成员用this限定。它只能在类和子类中用this访问,它不能被声明类或子类的其他实例访问,例如

    class Base{
        protected val alpha ="Alpha";
        protected[this] def sayHello = "Hello";
        def foo = Console println(new Base().sayHello) // won't compile
        def bar = Console println(this.sayHello)
    }
    class Derived extends Base{
            def hello = println(this.sayHello) ;
            //def hello2 = println((new Derived() .sayHello) // won't compile
    }
    

    由于默认情况下 Scala 不支持受保护成员的包级别访问。但是如果您想让它在包级别可用,那么您需要明确指定包,例如protected[pkg]。现在,如果在 pkg 或以下声明的类中访问该受保护成员,则通过声明类/子类实例可以看到它们。

    例如

    package com.test.alpha{
    class Base{
        protected val alpha ="Alpha";
        protected[test] def sayHello = "Hello"; // if you remove [test] it won't compile
    }
    
    class Derived extends Base{
        val base = new Base
            def hello = println(base.sayHello) ;
    }}
    

    这就是人们如何记住 Scala protected

    【讨论】:

      【解决方案2】:

      区别在于protected[this]的子类实例只能访问自己的字段(this.x),而protected的子类可以访问所有实例中的字段(不仅是this):

      class Base{
        protected val alpha ="Alpha";
        protected[this] def sayHello = "Hello";
      }
      
      class Derived extends Base{
        def hello = println(this.alpha +" "+this.sayHello) ;
        def hello2 = println(
         new Derived().alpha +" "
         +new Derived().sayHello) ; // error on "sayHello"
      }
      

      在此代码中,您可以访问this.sayHello,但不能访问other.sayHello。 protected alpha 没有这个限制。

      【讨论】:

      • 你的意思是我可以在Derived中访问base.alpha
      • 我按照你的要求试过了,但结果一样,我使用的是 Scala 2.11.7
      • ProtectedDemo.scala:7: 错误:无法在 Base 中访问类 Base 中的值 alpha 不允许访问受保护的值 alpha,因为前缀类型 Base 不符合访问所采用的类 Derived放置 def hello = println(base.alpha) ;
      • 没错,使用[this] 限定的成员只能使用this 限定符访问。如果我需要使用 Base 实例访问 alpha 而不是使用 protected[pkg_of_scbclass] 来限定它,对吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-08
      • 2014-04-26
      • 1970-01-01
      • 1970-01-01
      • 2011-05-20
      相关资源
      最近更新 更多