采用抽象超类实例和“不允许访问受保护方法”错误的受保护方法

Posted

技术标签:

【中文标题】采用抽象超类实例和“不允许访问受保护方法”错误的受保护方法【英文标题】:protected method that takes an abstract super class instance and the "access to protected method not permitted" error 【发布时间】:2020-04-23 01:39:36 【问题描述】:

我设计了一个相当简单的例子来说明我的观点,如下所示:

abstract class AbstractSuperClass 
  protected def someFunction(num: Int): Int
  def addition(another: AbstractSuperClass, num: Int): Int


class SubclassSquare extends AbstractSuperClass 
  override protected def someFunction(num: Int): Int = num * num
  override def addition(another: AbstractSuperClass, num: Int): Int =
    someFunction(num) + another.someFunction(num)

我在执行代码时收到以下错误消息。 (当然,main 函数是正确定义的。)

Error:(12, 33) 类 AbstractSuperClass 中的方法 someFunction 无法在 AbstractSuperClass 中访问 不允许访问受保护的方法 someFunction,因为 前缀类型 AbstractSuperClass 不符合 class 访问发生的子类 someFunction(num) + another.someFunction(num)

addition 方法导致了问题。该代码尝试访问 AbstractSuperClass 实例的受保护字段,但从我的角度来看,它在这里应该没有问题,因为 SubclassSquareAbstractSuperClass 的子类。

但是,我知道这里肯定有一些我不明白的地方。我想知道如何更改我的代码以使其编译。好评。

【问题讨论】:

您似乎无法访问另一个实例上的protected 字段。但是,这对我来说似乎是一个错误。 是的,通常你可以访问另一个对象的受保护字段,只要它们都是同一个类的实例。从技术上讲,参数anotherthis 都是AbstractSuperClass 的实例,所以人们会认为它有效,但显然不是。 开场截击加一个,或者如果你愿意,莎莉。我希望他们为错误跟踪器添加一个模板,开头是:“我设计了一个相当简单的例子来说明我的观点,如下所示。” 【参考方案1】:

您可以扩大访问范围:

package prot

abstract class AbstractSuperClass 
  protected[prot] def someFunction(num: Int): Int
  def addition(another: AbstractSuperClass, num: Int): Int


class SubclassSquare extends AbstractSuperClass 
  override protected[prot] def someFunction(num: Int): Int = num * num
  override def addition(another: AbstractSuperClass, num: Int): Int = someFunction(num) + another.someFunction(num)

规范词:

受保护的标识符 x 可以用作选择中的成员名称 r.x

仅在以下情况之一适用时:

访问权限在定义成员的模板内,或者,如果资格 C 在包 C 或类 C 或其伴侣中给出 模块,或

r 是 this 和 super 的保留字之一,

或 r 的类型符合包含访问权限的类的类型实例。

所以访问权限取决于您选择的内容。

你违反了第三个条件,第一个是补救措施。

【讨论】:

【参考方案2】:

在 scala 中,protected 比在 java 中更严格。

我发现 this answer 在理解 scala 的受保护修饰符时非常有帮助。

如果受保护的成员不合格(即它只是普通受保护的) 然后它与另一个声明类的实例可见 将类以及 this 声明到类和子类中。

所以你可以修改SubclassSquare中的加法函数如下:

override def addition(another: AbstractSuperClass, num: Int): Int =
      someFunction(num) + another.asInstanceOf[SubclassSquare].someFunction(num)

这段代码可以编译,但如果参数不是SubclassSquare 的实例,它会崩溃,所以这不是一个好的解决方案。

更好的方法是使用访问限定符。因此,您只需要使用受保护的修饰符指定您的包名称,例如protected[yourPackageName]。这样做将使您的受保护成员可以在声明的包中或以下的类中访问。所以你的代码看起来像:

abstract class AbstractSuperClass 
    protected[yourPackageName] def someFunction(num: Int): Int
    def addition(another: AbstractSuperClass, num: Int): Int
  

  class SubclassSquare extends AbstractSuperClass 
    override protected[yourPackageName] def someFunction(num: Int): Int = num * num
    override def addition(another: AbstractSuperClass, num: Int): Int =
      someFunction(num) + another.someFunction(num)
  

【讨论】:

以上是关于采用抽象超类实例和“不允许访问受保护方法”错误的受保护方法的主要内容,如果未能解决你的问题,请参考以下文章

在抽象超类的静态方法中创建子类的实例? [复制]

超类中的受保护方法在不同包中的子类中是不是可见? [复制]

创建类的受保护构造函数有啥好处和坏处

我们可以声明一个抽象方法来返回抽象超类中的子类对象而不需要新的实例化吗?

抽象abstract

抽象类的受保护与公共构造函数?有区别吗?