1

J'ai une classe abstraite avec un objet et une sous-classe concrète représentant un arbre binaire pour trier un groupe de chaînes lexicographiquement.comment hériter un protégé/privé d'une classe abstraite dans Scala

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 
} 

Je veux mettre en œuvre une méthode pour obtenir la plus grande chaîne, en utilisant uniquement les méthodes déjà créées pour cette classe d'une manière « fonctionnelle ». J'ai utilisé la méthode "la plus grande" sans paramètre qui renvoie une chaîne, qui appelle une autre méthode "bigIter" qui s'appelle récursivement jusqu'à ce qu'elle traverse tout l'arbre.

Mon idée a fonctionné, mais je veux cacher l'implémentation de bigIter, pour qu'un utilisateur puisse seulement voir la méthode "Biggest". J'ai utilisé protégé et privé pour bigIter sur les classes abstraites et concrètes, mais cela n'a pas fonctionné. J'ai essayé d'utiliser private avec la méthode bigIter dans la classe abstraite, mais les méthodes privées d'une superclasse ne peuvent pas être héritées. J'ai essayé avec trop protégé, en l'utilisant à la fois la superclasse et les sous-classes, obtenir l'erreur suivante

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 ^

Toute idée de comment cela pourrait-il se faire?

note: 1. appel plus grand sur vide devrait renvoyer une erreur, c'est pourquoi j'appelle "bigIter" des classes concrètes.
2. Ceci est pour un cours que je fais, donc l'idée n'est pas d'utiliser des fonctions de liste d'ordre supérieur.

+1

* "J'ai utilisé protégé et privé pour bigIter sur les classes abstraites et concrètes, mais cela n'a pas fonctionné." * Qu'est-ce qui n'a pas fonctionné? Quelle était l'erreur? –

+0

Si je comprends bien votre définition de "plus grand", ne devriez-vous pas seulement regarder le sous-ensemble 'right'? –

+0

Les objets 'private' ne sont pas hérités. Qu'est-ce qui n'a pas fonctionné à propos de 'protected'? –

Répondre

2

SI-9890 explique pourquoi le compilateur n'est pas satisfait lorsque vous essayez d'accéder à une méthode sur un type super dans une instance de type dérivé. The specification restricts this:

A protected identifier x may be used as a member name in a selection r.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 package C , or the class C , or its companion module, or
  • r is one of the reserved words this and super, or
  • r's type conforms to a type-instance of the class which contains the access.

Le dernier point signifie essentiellement r, qui dans votre cas est StringSet, doit être de type NonEmpty. Pour contourner ce problème, vous pouvez placer toutes vos implémentations de StringSet sous le même package et définir un protected[package] sur bigIter. Par exemple, supposons que votre nom de package est foo, vous pouvez faire:

protected[foo] def bigIter(acc: String): String 

Et maintenant, il va compiler.