admin管理员组

文章数量:1356575

The scala project is depending on the Java lib that I cannot modify. I need to extend one of the Java classes and override method, however I have issues with protected visibility:

package com.a;

class Foo {
   protected Baz protectedBaz;

   Foo(Int i) { ... }
   Foo(String s) { ... }

   protected void init() { ... }
}

package com.b;

class BarFoo extends Foo {

   BarFoo(Int i) { ... }
   BarFoo(String s) { ... }
}

Now, In scala I need to extend BarFoo, override the init method and modify the protectedBaz:

override def init(): Unit = {
   super.init() // I need BarFoo to do its work
   this.protectedBaz.setA(..)
}

End of problem statement


Attempt

Before I even get there, I need to deal with the constructor problem. I followed the solution here:

object CustomBarFoo {
   def apply(i: Int) = new BarFoo(i) with CustomBarFoo
   def apply(s: String) = new BarFoo(s) with CustomBarFoo
}

trait CustomBarFoo extends BarFoo {
   override def init(): Unit = {
       super.init()
       this.protectedBaz.setA(..) <<< Implementation restriction: trait CustomBarFoo accesses protected variable protectedBaz inside a concrete trait method.
   }
}

The suggested solution here is to subclass and redefine visibility.

I have a classical chicken and egg problem. I cannot create a subclass class CustomBarFoo extends BarFoo because of the constructor issues. But the only way to redefine the visibility is to subclass.

The scala project is depending on the Java lib that I cannot modify. I need to extend one of the Java classes and override method, however I have issues with protected visibility:

package com.a;

class Foo {
   protected Baz protectedBaz;

   Foo(Int i) { ... }
   Foo(String s) { ... }

   protected void init() { ... }
}

package com.b;

class BarFoo extends Foo {

   BarFoo(Int i) { ... }
   BarFoo(String s) { ... }
}

Now, In scala I need to extend BarFoo, override the init method and modify the protectedBaz:

override def init(): Unit = {
   super.init() // I need BarFoo to do its work
   this.protectedBaz.setA(..)
}

End of problem statement


Attempt

Before I even get there, I need to deal with the constructor problem. I followed the solution here:

object CustomBarFoo {
   def apply(i: Int) = new BarFoo(i) with CustomBarFoo
   def apply(s: String) = new BarFoo(s) with CustomBarFoo
}

trait CustomBarFoo extends BarFoo {
   override def init(): Unit = {
       super.init()
       this.protectedBaz.setA(..) <<< Implementation restriction: trait CustomBarFoo accesses protected variable protectedBaz inside a concrete trait method.
   }
}

The suggested solution here is to subclass and redefine visibility.

I have a classical chicken and egg problem. I cannot create a subclass class CustomBarFoo extends BarFoo because of the constructor issues. But the only way to redefine the visibility is to subclass.

Share Improve this question edited Apr 1 at 3:19 Hedrack asked Mar 28 at 3:58 HedrackHedrack 7871 gold badge7 silver badges20 bronze badges 2
  • What versions of Scala and Java are you using? – Dmytro Mitin Commented Mar 28 at 16:29
  • It's scala 2.12 and java 8 – Hedrack Commented Mar 30 at 20:17
Add a comment  | 

1 Answer 1

Reset to default 1

In Scala 2.13.16 the full error message is

Implementation restriction: trait CustomBarFoo accesses protected variable protectedBaz inside a concrete trait method.
Add an accessor in a class extending class Foo as a workaround.  <-- !!!

Even if you can't modify Java library, you still can define your own Java class providing a public accessor to the protected field:

public class SubBarFoo extends BarFoo {
    public SubBarFoo(int i) {
        super(i);
    }

    public SubBarFoo(String s) {
        super(s);
    }

    public Baz getProtectedBaz() {
        return protectedBaz;
    }
}

And now you should be able to use this accessor in Scala:

object CustomBarFoo {
  def apply(i: Int) = new SubBarFoo(i) with CustomBarFoo
  def apply(s: String) = new SubBarFoo(s) with CustomBarFoo
}

trait CustomBarFoo extends SubBarFoo {
  override def init(): Unit = {
    super.init()
    this.getProtectedBaz.setA()
  }
}

One more option is to define CustomBarFoo in your Scala code in the same package as Foo in the Java library. Scala protected members are accessible in inheritors but Java protected members are accessible also in the same package.

本文标签: scalaSubclassing and overriding Java class with protected field accessStack Overflow