Tek amacı dolaylı olarak başka bir sınıfa dönüştürülecek sınıflar oluşturmak kötü mü?


10

CircleNesneleri oluşturmanıza izin veren bir kitaplık kullandığımız, onu tanımlamak için dairenin yarıçapını ve merkezini belirtebileceğiniz bir durum düşünün . Ancak, bazı nedenlerden dolayı, gerekli bir flavourparametreyi de alır . Şimdi Circlekendi uygulamamda gerçekten kullanmam gerektiğini söyleyelim , ancak uygulamamın amaçları için Flavours.Cardboardher seferinde lezzeti ayarlayabilirim .

Bunu "çözmek" için Circle, sadece radiusve alır centerparametre olarak farklı bir ad alanında kendi sınıf oluşturmak , ama Circlesadece bir Circle(this.radius, this.center, Flavours.Cardboard)nesne oluşturan harici kütüphanenin sınıfına örtük bir dönüştürücü vardır . Yani diğer türlere ihtiyacım olan her yerde Circle, otomatik dönüşümün gerçekleşmesine izin verdim.

Böyle bir sınıf yaratmanın sonuçları nelerdir? Daha iyi çözümler var mı? Uygulamamın bu harici kütüphanenin üzerine kurulmuş ve diğer programcılar tarafından kullanılmak üzere tasarlanmış bir API olması fark eder mi?


Bu, Adaptör Kalıbının bir varyasyonu gibi görünüyor , ancak burada şüpheli bir değer gibi görünüyor (sadece bir parametre ayarlamaktan kaçınmak için bir kolaylık).
Robert Harvey

5
Neden bir MakeCircle işlev yaratmıyorsunuz ?
user253751

1
@immibis Thay ilk düşüncemdi. Oyun yaparken, genellikle makePlayerkendi çizgisinde bir işlev yaratacağım, sadece oyuncuyu yerleştirmek için koordinatları kabul eder, ancak çok daha karmaşık bir kurucuya delege olur.
Carcigenicate

Yanıtlar:


13

Her zaman kötü olmasa da, örtük dönüşümlerin en iyi seçeneğiniz olması oldukça nadirdir.

Sorunlar var.

  1. Örtük dönüşümler çok okunabilir değildir.
  2. Yeni bir nesne yaptığınız için, orijinal nesnede yapılan değişiklikler dönüştürdüğünüz nesne tarafından görülmeyecek ve hatalara yol açacaktır.
  3. Nesneyi atıyorsanız, temizlemek için ekstra çöp.
  4. Bir sorun varsa, dönüşüm gerçekleştiğinde gerçekleşir, şey oluşturulduğunda değil, izlenmesi daha zor olan hatalar olur.

Genel olarak, daha iyi çözümler var.

  1. Diğer sınıfı / çerçeveyi dahili olarak kullanan kendi ince paketleyicinizi yapın.
  2. İstediğiniz constuctor argümanlarını alan ve sabit olanı sağlayan bir yardımcı yöntem yapın, umursadığınız argümanı belirtmek zorunda kalmadan gerçek nesneyi döndürün.
  3. Problem sınıfından miras alın ve kendi, daha güzel kurucunuzu sağlayın.
  4. Ekstra argümandan geçmenin gerçekten büyük bir anlaşma olmadığını anlayın.

Kişisel olarak, # 2'yi uygulamak için en basit ve tasarım üzerinde en az külfetli buluyorum. Durum ve bu sınıflarla başka ne yapmaya çalışıyorsanız, diğerleri iyi olabilir.

Örtük dönüşüm son çare ve sadece yapmaya çalıştığım C ++ tarzı functors varsa bana gerçekten buna değer görünüyor - örtük olarak temsilci türlerine dönüştürmek strateji nesneleri.


1

Tanımladığınız senaryo göz önüne alındığında, bunu kısmi işlev uygulaması açısından düşünebilirsiniz.

Bir kurucu bir işlevdir (en azından teoride; C # 'da kurucuyu çağıran bir "fabrika işlevi" oluşturabilirsiniz):

Func<double, Point, Flavour, Circle> MakeCircle = (r, p, f) => new Circle(r, p, f);

kısmi uygulama için aşağıdakiler yeterli olacaktır:

public static Func<T1, T2, R> Partial<T1, T2, T3, R>(this Func<T1, T2, T3, R> func, T3 t3)
   => (t1, t2) => func(t1, t2, t3);

Artık sadece 2 parametre gerektiren kurucunuzu alabilirsiniz:

Func<double, Point, Circle> MakeCardboardCircle = Circle.Partial(Flavours.Cardboard)

Şimdi istediğiniz parametreleri içeren bir fabrika fonksiyonuna sahipsiniz

Circle c = MakeCardboardCircle(1.0, new Point(0, 0)))

BTW, bu daha işlevsel bir perspektiften yukarıdaki seçenek 2'ye açıkça eşdeğerdir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.