Modification due à la combinaison d'un exemple trop complexe et de l'absence d'indication claire de mes intentions.

J'ai un class à partir duquel les concepteurs vont s'étendre et construire. Pour garder le code propre, j'aimerais pouvoir effectuer une combinaison d'actions lorsque des classes spécifiques sont instanciées.

Je sais que je peux utiliser un objet compagnon avec apply() personnalisé pour faire la plupart de cela, et fonctionnerait à l'exception du fait que j'ai en quelque sorte besoin de connaître la classe qui instancie la classe spécifique (et j'essaie de éviter de passer this en paramètre).

class Apple{}
class Orange{}
class MyBase{
  val allApples  = ListBuffer[Apple]()
  val allOranges = ListBuffer[Orange]()
}

//User defined classes extending MyBase

class SomeNewClass extends MyBase{
  val apple1 = new Apple   //we would want to add apple1 to the allApples List
  val apple2 = new Apple
  val orange1 = new Orange

}

class AnotherClass extends MyBase{
  val someClass = new SomeNewClass

  val apple1 = new Apple
}


Vous pouvez donc voir que je veux pouvoir ajouter les instances Apple à allApples ListBuffer et de même pour les oranges. J'aimerais pouvoir le faire sans requérir une méthode de type addApple. Le problème est que je n'ai aucune référence à SomeNewClass ou AnotherClass (ou à tout ce que le concepteur ferait). Je pourrais avoir un implicite comme le suivant :

class Apple()(implicit myBaseCaller : MyBase){
  myBaseCaller.addApple(this)
}
class MyBase{
  implicit val myself : MyBase = this
  //excluded for clarity
}

Instancier un nouvel Apple ou Orange en dehors d'une classe qui étend MyBase serait une violation du DSL dans ce cas particulier.

Je ne conteste donc pas que la meilleure solution serait une méthode explicite pour ajouter des pommes, mais j'essaie de voir s'il existe une solution plus simple pour le codage.

Il n'y a peut-être pas une façon décente de le faire, ce qui serait bien. Dans ce cas, cela ne me dérange pas un peu de surcharge dans les classes de base pour rendre les classes étendues plus faciles à écrire.

Suppression de la question d'origine car trop compliquée

0
l Steveo l 9 févr. 2020 à 23:00

1 réponse

Meilleure réponse

Instancier un nouvel Apple ou Orange en dehors d'une classe qui étend MyBase serait une violation du DSL dans ce cas particulier.

Le contexte n'indique pas clairement si cela serait souhaitable ou non.

En tout cas, avez-vous pensé à ce qui pourrait être accompli avec un constructeur privé et un constructeur auxiliaire public ?

import scala.collection.mutable.ListBuffer

class MyBase{
  class Apple private (lb :ListBuffer[Apple]) {
    lb += this
    def this() = this(allApples)
  }
  class Orange private (lb :ListBuffer[Orange]) {
    lb += this
    def this() = this(allOranges)
  }
  val allApples  = ListBuffer[Apple]()
  val allOranges = ListBuffer[Orange]()
}

class SomeNewClass extends MyBase{
  val apple1 = new Apple
  val apple2 = new Apple
  val orange1 = new Orange
}

class AnotherClass extends MyBase{
  val someClass = new SomeNewClass
  val apple1 = new Apple
}

val snc = new SomeNewClass
val ac = new AnotherClass
snc.allApples.size   //res0: Int = 2
snc.allOranges.size  //res1: Int = 1
ac.allApples.size    //res2: Int = 1
ac.allOranges.size   //res3: Int = 0
2
jwvh 10 févr. 2020 à 09:15