Reputation: 1043
I've got an abstract class with an object and a concrete subclass representing a binary tree for sorting a group of strings lexicographically.
abstract class StringSet {
def incl(x:String):StringSet
def contains(x:String):Boolean
def union(that:StringSet):StringSet
def biggest:String // this is my new method
def bigIter(acc:String):String //this is my new helper method
}
object Empty extends StringSet {
override def toString: String = "."
def incl(x: String): StringSet = new NonEmpty(x, Empty, Empty)
def contains(x: String): Boolean = false
def union(that:StringSet):StringSet = that
def biggest:String = throw new java.util.NoSuchElementException("...")
def bigIter(acc:String):String = acc
}
class NonEmpty(elem:String, left:StringSet, right:StringSet) extends StringSet {
def incl(x: String): StringSet = {
if (x < elem) new NonEmpty(elem, left incl x, right)
else if (x > elem) new NonEmpty(elem, left, right incl x)
else this
}
def contains(x: String): Boolean = {
if (x < elem) left contains x
else if (x > elem) right contains x
else true
}
def union(that:StringSet):StringSet = ((left union right) union that) incl elem
def biggest:String = bigIter(elem)
def bigIter(acc:String):String =
if (elem < acc) left union right bigIter acc
else left union right bigIter elem
}
I want to implement a method for obtaining the biggest string, using only the already created methods for that class in a "functional way". I used the method "biggest" with no parameters that return a string, that calls another method "bigIter" who recursively call itself until it traverses all the tree.
My idea worked, but I want to hide the bigIter implementation, in order for a user could only see the method "Biggest". I used protected and private for bigIter on the abstract and concrete classes, but it didn't work. I tried using private with bigIter method in the abstract class, but private methods of a superclass cannot be inherited. I tried with protected too, using it with both the superclass and the subclasses, getting the following error
Error:(50, 39) method bigiter in class StringSet cannot be accessed in A$A3.this.StringSet Access to protected method bigiter not permitted because prefix type A$A3.this.StringSet does not conform to class NonEmpty in class A$A3 where the access take place if (elem < acc) left union right bigiter acc ^
Any ideas of how could this be accomplished?
note:
1. calling biggest on Empty should return an error, so that's why I call "bigIter" from the concrete classes.
2. This is for a course I'm doing, so the idea is not to use higher order list functions.
Upvotes: 2
Views: 1282
Reputation: 149518
SI-9890 explains why the compiler isn't happy when you try to access a method on a super type in a derived type instance. The specification restricts this:
A protected identifier
x
may be used as a member name in a selectionr.x
only if one of the following applies:
- The access is within the template defining the member, or, if a qualification
C
is given, inside the packageC
, or the classC
, or its companion module, orr
is one of the reserved words this and super, orr's
type conforms to a type-instance of the class which contains the access.
The last bullet basically means r
, which in your case is StringSet
, must be of type NonEmpty
.
To get around this, you can place all your implementations of StringSet
under the same package and have a protected[package]
set on bigIter
. For example, assume your package name is foo
, you can do:
protected[foo] def bigIter(acc: String): String
And now it will compile.
Upvotes: 3