Verileri yapıcıya yöntem parametreleri yerine geçirirken sınıf kavramı nasıl değişir?


12

Diyelim ki bir ayrıştırıcı yapıyoruz. Bir uygulama şunlar olabilir:

public sealed class Parser1
{
    public string Parse(string text)
    {
       ...
    }
}

Ya da metni yapıcıya aktarabiliriz:

public sealed class Parser2
{
    public Parser2(string text)
    {
       this.text = text;
    }

    public string Parse()
    {
       ...
    }
}

Her iki durumda da kullanım kolaydır, ancak parametre girişini diğerine göre etkinleştirmek ne anlama gelirParser1 ? API'ye baktıklarında bir programcıya hangi mesajı gönderdim? Ayrıca, bazı durumlarda teknik avantajlar / dezavantajlar var mı?

Başka bir soru, ikinci uygulamada bir arayüzün oldukça anlamsız olacağını fark ettiğimde ortaya çıkıyor:

public interface IParser
{
    string Parse();
}

... ilk arayüzdeki bir arayüzün en azından bir amaca hizmet edebileceği bir yer. Bu, özellikle bir sınıfın "birbirine bağlanabilir" olup olmadığını gösterir mi?


OO'nun anlambiliminin aslında niyeti nasıl ifade ettiği hakkında ilk kez bazı yararlı Soru ve Cevaplar gördüm. Şimdiye kadar hepsi sadece sözdizimsel şeker oldu, bana göre.

Yanıtlar:


11

Anlamsal olarak konuşursak, OOP'de kurucuya sadece sınıfı oluşturmak için gereken bir dizi parametreyi iletmelisiniz - benzer şekilde bir yöntemi çağırdığınızda, sadece iş mantığını yürütmek için gereken parametreleri iletmelisiniz.

Yapıcıda geçirmeniz gereken parametreler, varsayılan varsayılan değere sahip olmayan parametrelerdir ve sınıfınız değiştirilemezse (veya gerçekten a struct), varsayılan olmayan all özelliklerinin geçirilmesi gerekir.

İki örneğinizle ilgili olarak:

  • yapıcıya geçerseniz text, Parser2sınıfın söz konusu metin örneğini daha sonra ayrıştırmak için özel olarak oluşturulacağını ima eder . Belirli bir ayrıştırıcı olacaktır. Bu tipik olarak sınıfın oluşturulması çok pahalı veya süptil olduğunda, yapıcıda bir RegEx derlenebilir, bu nedenle bir örneği tuttuğunuzda, derleme maliyetini ödemek zorunda kalmadan yeniden kullanabilirsiniz; başka bir örnek PRNG'yi başlatmaktır - nadiren yapılması daha iyidir.
  • textyönteme geçerseniz , Parser1farklı metinleri aramalarla ayrıştırmak için yeniden kullanılabileceğini gösterir.

3
Parser1'in durumu koruduğu bir zayıf sinyal olduğunu ekliyorum - yani belirli bir metin dizesi daha önce tat örneğinde yapılmış olmasına bağlı olarak farklı sonuçlar üretebilir. Bu mutlaka böyle değildir, ama olabilir.
jmoreno

8

Bir değişkeni yapıcı parametresi olarak geçirmenin ne anlama geldiğini hatırlayalım: Bir nesneyi, örnek değişkenlerini nesne yöntemlerinde kullanmak için başlatırsınız. Mesele şu ki , sınıfınızda yüksek bir uyum sağlamak istediğiniz için muhtemelen birden fazla yöntemde kullanmak istersiniz .

Bir parametreyi doğrudan bir yönteme geçirmek, bir nesneye mesaj göndermek ve muhtemelen bir cevap almak anlamına gelir. Böylece, müşteri nesnenin kendisine bir hizmet sunmasını ister.

Sonuç olarak, bunlar parametreleri geçirmek için iki farklı yöntemdir ve dahili olarak bazı bilgileri yönetirken nesnenizin bir hizmet sunması ya da doğası gereği bazı işlevler sağlaması gerekip gerekmediğini seçmelisiniz.


+1. Uyum yöntem veya kurucuya ait olup olmadığına nasıl karar veririm.
jhewlett

4

Her iki durumda da kullanım kolaydır, ancak Parser1'e parametre girişini diğerine kıyasla etkinleştirmek ne anlama gelir?

Bu temel bir tasarım değişimi. Ve tasarım niyet ve anlam taşımalıdır. Ayrıştırmak istediğiniz her dize için ayrı nesneleriniz olması gerekiyor mu? Başka bir deyişle, neden stringX ile ayrıştırıcı örneğine ve stringY ile başka bir örneğe ihtiyacımız var? Ayrıştırma (ing) ve ikisinin birlikte yaşaması ve ölmesi gereken verilen dize nedir? "Robert Harvey'in dediği gibi" temeldeki [ayrıştırma] uygulamasının değişmediğini varsayarsak, hiçbir anlamı yoktur. Ve o zaman bile tartışmalı IMHO.

Verileri yapıcıya yöntem parametreleri yerine geçirirken sınıf kavramı nasıl değişir?

Yapıcı parametreleri bana bu nesnelerin bir şey için gerekli olduğunu söylüyor. Bunlar olmadan uygun durum garanti edilmez. Ayrıca, bir ayrıştırıcının diğerinden temel olarak nasıl / neden farklı olduğunu biliyorum.

Yapıcı parametreleri, sınıfın nasıl kullanılacağı hakkında çok fazla bilgi sahibi olmamı engelliyor. Bunun yerine belirli özellikleri ayarlamam gerekiyorsa - bunu nasıl bilebilirim? Bir kutu solucan açılır. Hangi özellikler? Hangi sırayla? Hangi yöntemleri kullanmadan önce? ve bunun gibi.

Başka bir soru, ikinci uygulamada bir arayüzün oldukça anlamsız olacağını fark ettiğimde ortaya çıkıyor:

API'da olduğu gibi bir arayüz, istemci koduna maruz kalan yöntemler ve özelliklerdir. public interface { ... }Sadece sarılmayın . Yani arayüzün anlamı ya-veya yapıcı vs yöntem parametresi ikilemindedir, NOT public interface Iparservspublic sealed class Parser

sealedSınıf garip. Farklı ayrıştırıcı uygulamaları düşünürsem - "Iparser" dan bahsettiniz - o zaman miras benim ilk düşüncemdir. Düşüncemde sadece kavramsal bir uzantı. IE tüm ParserXs temelde Parsers. Başka nasıl söylenir? ... Alman Shepard bir köpek (kalıtım), ama papağanımı havlamaya eğitebilirim (köpek gibi davran - "arayüz"); ama Polly, sadece bir köpekbalığı alt kümesi öğrenmiş gibi davranan bir köpek değildir. Sınıflar, soyut veya başka türlü, arayüzler kadar mükemmel bir şekilde hizmet eder .


Bir ayrıştırıcı gibi yürür ve bir ayrıştırıcı gibi konuşursa, bu ... bir ördek!

2

Sınıfın ikinci versiyonu değişmez hale getirilebilir.

Arayüz, temeldeki uygulamayı değiştirmeyi sağlamak için hala kullanılabilir.


Verileri sınıf içinde işlevsel bir şekilde aktararak ilk versiyonda da değişmez hale getirilemez mi?
ciscoheat

2
Kesinlikle. Ancak değişmezliğin genel modeli, yapıcıyı kullanarak sınıf üyelerini ayarlamak ve salt okunur özelliklere sahip olmaktır. Fonksiyonel programlama için bir sınıfa bile ihtiyacınız yoktur.
Robert Harvey

Scylla ve Charybdis: OO veya değişmez verileri seçer miyim? Daha önce hiç böyle duymadığını duymadım.

2

Parser1

Varsayılan bir kurucu ile oluşturma ve girdi metnini bir yönteme geçirme, Parser1 öğesinin yeniden kullanılabilir olduğunu gösterir.

Parser2

Giriş metninin yapıcıya iletilmesi, her bir giriş dizesi için yeni bir Parser2 oluşturulması gerektiğini gösterir.


Elbette, eğer onu bir sonraki seviyeye götürürsek, yeniden kullanılamaz bir nesne ile tekrar kullanılamaz bir nesne arasında ne sonuca varabiliriz?
ciscoheat

Bundan daha fazlasını kabul etmem, bunun yerine belgelere ertelemem.
Mike Partridge

Kimliğinin değiştiği "yeniden kullanılabilir bir nesne" sıralı olmayan bir şeydir. Ve yönetilen çerçevelerle, bir şeyleri atmak zorunda kalmayacağınız, sadece üzerine yazdığınız veya kapsam dışına çıkmadığınız anlamına gelir, kesinlikle gereksizdir. İnşa edin!
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.