supertype of another class.1 So the compiler would refuse the example code above that attempted to instantiate Currency.
However, you can work around this restriction using a factory method. Instead of creating an instance of an abstract type directly, declare an abstract method that does it. Then, wherever the abstract type is fixed to be some concrete type, you also need to give a concrete implementation of the factory method. For class AbstractCurrency, this would look as follows:
abstract class AbstractCurrency { |
|
|
type Currency <: AbstractCurrency |
// abstract type |
def make(amount: Long): Currency |
// factory |
method |
... |
// rest of |
class |
} |
|
|
A design like this could be made to work, but it looks rather suspicious. Why place the factory method inside class AbstractCurrency? This looks dubious, for at least two reasons. First, if you have some amount of currency (say, one dollar), you also hold in your hand the ability to make more of the same currency, using code such as:
myDollar.make(100) // here are a hundred more!
In the age of color copying this might be a tempting scenario, but hopefully not one which you would be able to do for very long without being caught. The second problem with this code is that you can make more Currency objects if you already have a reference to a Currency object, but how do you get the first object of a given Currency? You’d need another creation method, which does essentially the same job as make. So you have a case of code duplication, which is a sure sign of a code smell.
The solution, of course, is to move the abstract type and the factory method outside class AbstractCurrency. You need to create another class that contains the AbstractCurrency class, the Currency type, and the make factory method. We’ll call this a CurrencyZone:
abstract class CurrencyZone {
type Currency <: AbstractCurrency def make(x: Long): Currency
1 There’s some promising recent research on virtual classes, which would allow this, but virtual classes are not currently supported in Scala.