Этот случай (упрощенный до такой степени, что он не имеет особого смысла) правильно обрабатывается системой типов F #:
type HumanBeing() = class end
type Animal() = class end
type CreatureController() =
member this.Register creature = creature
type CreatureFactory() =
let anAnimal = new Animal()
let aHuman = new HumanBeing()
member this.GiveMeAnAnimal =
(new CreatureController()).Register anAnimal
member this.GiveMeAHuman =
(new CreatureController()).Register aHuman
Тип CreatureController.Register правильно выведен: 'a ->' a, поэтому его можно вызывать с двумя разными аргументами.
Теперь следующая версия имеет небольшое отличие: вместо передачи существа в качестве аргумента CreatureController.Register, оно передается его конструктору.
type HumanBeing() = class end
type Animal() = class end
type CreatureController(creature) =
member this.Register = creature
type CreatureFactory() =
let anAnimal = new Animal()
let aHuman = new HumanBeing()
member this.GiveMeAnAnimal =
(new CreatureController(anAnimal)).Register
member this.GiveMeAHuman =
(new CreatureController(aHuman)).Register
Этот второй пример не компилируется, поскольку Register выводится как Animal, поэтому вы не можете вызвать new CreatureController(aHuman)
.
(Примечание: в этом упрощенном случае Фабрика явно имеет недостатки, потому что она всегда возвращает одно и то же животное / человек, но это поведение не изменится, если вы замените anaimal / aHuman функциями.)
Почему CreatureControlled не создается как универсальный во втором случае? Это ограничение компилятора? Я скучаю по чему-то очень простому (все еще учусь ...)?