In a class in programming languages, my professor cites mixins as one of the solutions to the fragile base class problem. Wikipedia also used mixins to list (Ruby) as a solution to a fragile base class problem, but some time ago someone removed the mixins link. I still suspect that they may somehow have an advantage over inheritance in relation to the fragile base class problem. Otherwise, why did the professor say they help?
I will give an example of a possible problem. This is a simple Scala implementation of the problem (Java) that the professor gave us to illustrate the problem.
Consider the following base class. Assume that this is a very effective custom implementation of the list and that more operations are defined on it.
class MyList[T] { private var list : List[T] = List.empty def add(el:T) = { list = el::list } def addAll(toAdd:List[T]) : Unit = { if (!toAdd.isEmpty) { add(toAdd.head) addAll(toAdd.tail) } } }
Also consider the following attribute, which should add size to the list above.
trait CountingSet[T] extends MyList[T] { private var count : Int = 0; override def add(el:T) = { count = count + 1 super.add(el) } override def addAll(toAdd:List[T]) = { count = count + toAdd.size; super.addAll(toAdd); } def size : Int = { count } }
The problem is whether this feature will work, depends on how we implement addAll in the base class, that is, the functionality provided by the base class is "fragile", as would be the case with regular extends in Java or any another programming language.
For example, if we run the following code with MyList and CountingSet as defined above, we will go back 5 , whereas we expect to get 2 .
object Main { def main(args:Array[String]) : Unit = { val myCountingSet = new MyList[Int] with CountingSet[Int] myCountingSet.addAll(List(1,2)) println(myCountingSet.size) // Prints 5 } }
If we change addAll in the base class (!) As follows, the CountingSet flag works as expected.
class MyList[T] { private var list : List[T] = List.empty def add(el:T) = { list = el::list } def addAll(toAdd:List[T]) : Unit = { var t = toAdd; while(!t.isEmpty) { list = t.head::list t = t.tail } } }
Keep in mind that I am not an expert at Scala!