Переопределяющие конструкторы в F # - PullRequest
4 голосов
/ 02 апреля 2010

Как бы я написал следующий код C # на F #?

namespace Shared {
    public class SharedRegistry : PageRegistry {
        public SharedRegistry(bool useCache = true)
            : base(useCache) {
            // Repositories
            ForRequestedType<IAddressRepository>().TheDefaultIsConcreteType<SqlAddressRepository>();
            ForRequestedType<ISharedEnquiryRepository>().TheDefaultIsConcreteType<SharedEnquiryRepository>();

            // Services
            ForRequestedType<IAddressService>().TheDefaultIsConcreteType<AddressService>();
            ForRequestedType<ISharedEnquiryService>().TheDefaultIsConcreteType<SharedEnquiryService>();
        }
    }
}

Насколько мне удалось, но я не могу унаследовать от PageRegistry одновременно с объявлением моего собственного конструктора по умолчанию.

type SharedRegistry(useCache: bool) =
    inherit PageRegistry(useCache)
    new() = new SharedRegistry(true)

Rich

Ответы [ 2 ]

5 голосов
/ 02 апреля 2010

Я не уверен, что понимаю ваш вопрос; то, что вы написали выше, похоже, должно работать нормально. Если вы спрашиваете, куда поместить остальную логику конструктора, попробуйте это:

type SharedRegistry(useCache) as this =
  inherit PageRegistry(useCache)
  do
    this.ForRequestedType<IAddressRepository>().TheDefaultIsConcreteType<SqlAddressRepository>()
    // etc.
  new() = SharedRegistry(true)

Если вы хотите определить каждый конструктор индивидуально, вы можете сделать это тоже:

type SharedRegistry =
  inherit PageRegistry
  new(useCache) as this = 
    { inherit PageRegistry(useCache) } then
    this.ForRequestedType<IAddressRepository>().TheDefaultIsConcreteType<SqlAddressRepository>()
    // etc.
  new() = SharedRegistry(true)

Или вы можете использовать необязательный аргумент для вашего главного конструктора:

type SharedRegistry(?useCache) as this =
  inherit PageRegistry(defaultArg useCache true)
  do
    this.ForRequestedType<IAddressRepository>().TheDefaultIsConcreteType<SqlAddressRepository>()
    // etc.
4 голосов
/ 02 апреля 2010

Ваш класс C # использует параметры со значением по умолчанию, которое немного отличается от перегруженных конструкторов. В любом случае, F # поддерживает как перегруженные конструкторы, так и параметры по умолчанию.

Используя значения по умолчанию параметров, код будет выглядеть следующим образом:

type SharedRegistry(?useCache: bool) = 
    do 
      // constructor logic
    inherit PageRegistry(defaultArg useCache true) 

Теперь вы можете создать экземпляр следующим образом:

let r1 = new SharedRegistry() // using the default value
let r2 = new SharedRegistry(false) // specified explicitly
let r3 = new SharedRegistry(useCache=false) // using named parameter

Я считаю, что использование именованных параметров немного более элегантно в F #. Это работает так, что параметр useCache становится option<bool> под крышкой (это может быть проблемой, если вы хотите использовать класс из C #)

Относительно перегруженных конструкторов - Ваш код F # должен быть правильным (см. Ответ из kvb ). В целом, вероятно, лучше иметь хотя бы один неявный конструктор (так как это позволяет автоматически получать доступ к параметрам конструктора внутри тела класса, объявлять поля с помощью let и реализовывать логику конструктора с помощью do). Неявный конструктор должен быть тем, который принимает все параметры. В некоторых случаях вы можете захотеть сделать это приватным, что можно сделать так:

type SharedRegistry private (useCache: bool) = 
    inherit PageRegistry(useCache) 
    do 
      // constructor logic
    new () = SharedRegistry(true)
...