Veri türleri için belirli yöntemleri statik hale getirmenin mantığı nedir?

Aug 15 2020

C # 'da, örneğin, bir dizenin boş mu yoksa boş mu olduğunu söylemek, bir dizide bir öğe bulmak, bir diziyi temizlemek vb. İçin statik yöntemler vardır. diziler arasında eleman kopyalama yöntemleri.

Benzer şekilde, Python'da bir listenin uzunluğunu elde etmek, bir listeyi filtrelemek vb. İçin işlevler vardır, ancak bir öğenin dizinini bulmak ve listeyi kopyalamak için örnek yöntemler vardır.

Tersine, JavaScript'te, yerleşik bir veri türünde yapmam gereken hemen hemen her işleme örnek yöntemi veya özellik aracılığıyla erişilebilir.

Öyleyse, bazı şeyleri statik ve diğerlerini yapmamanın mantığı nedir?

DÜZENLEME : Açık olmak gerekirse, statik yöntemlerin amacını anlıyorum. Sorum daha çok, belirli yöntemlerin örnek yöntemler olarak yazılabilecekken neden statik olarak yazıldığıyla ilgilidir. C # ve Python'daki Finddiziler ve Formatdizeler için olduğu gibi .filterlen

Yanıtlar

2 AvnerShahar-Kashtan Aug 15 2020 at 15:09

DÜZENLEME : soru geliştirildi, bu yüzden cevabımı düzelteceğim, ancak yorumları alakasız hale getirmemek için bir öncekini aşağıda bırakacağım.

Muhtemelen farklı gerekçelere sahip farklı diller veya çerçeveler ile bir yöntemi bir örnek yöntem yerine statik bir yöntem olarak uygulamak için birkaç neden olabilir:

  1. Bir nesnenin genel arayüzü bir sözleşmedir. ArrayTürünüz bir Sortyöntemi ortaya çıkarırsa , bundan sonra dilin türü veya sürümü ne olursa olsun her dizinin onu desteklemesi gerekir. Bununla birlikte, bir Arraybellekteki verilerin yalnızca ince bir sözleşmeyle temsiliyse ve mantık, benzeri bir sınıfa taşınırsa Array.Sort, uyumluluğu bozmadan davranışınızı genişletmek veya değiştirmek için size daha fazla esneklik sağlar.

  2. Bob Martin'in Temiz Kodundan şu alıntıya bakın :

Nesneler davranışı açığa çıkarır ve verileri gizler; Veri yapısı verileri açığa çıkarır ve önemli bir davranışa sahip değildir "

Bu durumda Listsınıf, davranışı ortaya çıkaran bir sınıftır - verilerini gizler (yeniden boyutlandırılabilir bir dizi olarak uygulanır, ancak bu bir uygulama ayrıntısıdır), ancak işlevselliği ortaya çıkarır. Bir int[]olsa da, bir veri yapısıdır. Sıralı olarak ayrılmış bir intbloktur. Bir Lengthözelliği vardır çünkü verilerinin bir parçasıdır , ancak çok fazla davranışı yoktur - davranış, üzerinde çalışan bir sınıfa yüklenir .

  1. Biçimsel bir seçim olabilir. Python tamamen bir OO dili değildir ve Java / C # "her şey bir nesnedir" garantisine sahip olmayabilir, bu nedenle len()parametresinin bir nesne örneği olup olmadığına bakılmaksızın kullanılabilecek dil işlevlerini kullanmayı seçti .

Önceki Cevap

C #'daki statik yöntemlerin ardındaki mantık, bir türe bağlı ancak bir örneğe bağlı olmayan yöntemlere sahip olmaktır . Bunun birkaç nedeni olabilir:

  1. Her iki örneği üzerinde çalışabilir ve Yöntemler nullgibi, string.IsNullOrEmptydoğal olarak, örnek yöntemler olamaz - bir örneği olmayabilir çünkü.
  2. Benzer şekilde bir örnek oluşturan fabrika yöntemlerinin de çağrılabilecek bir örneği yoktur. Örneğin, kullanımdan kaldırılan birisi statik WebRequest.Create()yöntemi, türetilen bir türün yeni bir örneğini döndürür WebRequest.
  3. Unutulması kolay olsa da, .NET'in yerel bir integral türü ( int i =5) ve çevresinde kutulu bir referans türü ( ) için farklı bir kullanımı vardır object boxed = 5. Bir değer türünde ( int i = 5; t.ToString();) bir yöntemi çağırırsanız , onu kutulamanın bir maliyeti olur. Bu nedenle, bazı işlemler bir nesne üzerinde bir yöntem olarak değil, bir değeri kabul eden statik bir yöntem olarak tanımlanır. Bu nedenle, matematiksel işlemler Math.Abs, kutulu türlerde yöntemler olarak değil, değerleri alan ve döndüren statik işlevler olarak tanımlanır.
  4. Bazen bir türü "yapılandırmak" için statik yöntemler kullanılır, belirli bir örneği değil, sistemdeki bu türün davranışını. Örneğin, [ServicePointManager.SetTcpKeepAlive()][1].NET'te paylaşılan HTTP (s) yığınını kullanan tüm sınıfların davranışını yapılandırır, böylece hepsini bu statik yöntemlerle yapılandırabilirsiniz.
5 amon Aug 15 2020 at 15:28

Statik yöntemler çok mantıklı

  • yöntem türle ilişkili olduğunda, ancak mevcut bir örneği gerektirmediğinde; veya
  • dil yalnızca sınıflar aracılığıyla ad alanını desteklediğinde.

C # yalnızca sınıfların üyeleri olarak işlevleri destekler, bu nedenle yardımcı işlevler statik yöntemler olarak yazılmalıdır. C # Mathsınıfı en iyi örnektir.

JavaScript'in sınıfları yoktur, ancak yerel olmayan her değişken bir nesneyle ilişkilendirilir - tarayıcıda çoğu API'ye windownesne aracılığıyla erişilebilir . Bununla birlikte, sınıf benzeri bir nesne aracılığıyla erişilebilen yöntemler vardır, örn Array.isArray(x).

Python, çoğunlukla nesne yönelimli, kendine özgü bir tasarıma sahiptir, ancak büyük ölçüde tarihsel nedenlerden dolayı len()veya gibi bazı yerleşik işlevlere sahiptir iter(). Başlık altında, gerçek yöntemleri çağırırlar, örneğin iter(x)genellikle x.__iter__()bir liste gibi indekslenebilen nesneler için bir geri dönüş ile.

Daha ilginci static, dilin tuhaflıkları nedeniyle değil, mantıklı olduğu için yöntemlerdir. Yapıcı benzeri veya fabrika benzeri yöntemler, üzerinde bir yöntem çağırabileceğimiz mevcut bir nesneye sahip olmadığımız klasik örnektir. Bazı işlevler aynı zamanda tam olarak bir nesne üzerinde çalışmaz, örneğin String.IsNullOrEmpty(x)sıfır veya bir nesne üzerinde çalışır. Bu bir yöntem olarak çalışmaz, örneğin x.IsNullOrEmpty()boşsa bir istisna atar! Array.isArray(x)JS yöntemi başka bir büyük örneğidir: dediğimiz istiyoruz isArray(x)sadece diziler üzerinde, herhangi tür nesneler üzerinde. Bu nedenle, bir örnek yöntemi, her nesnenin prototipinin bir parçası olmadığı sürece çalışmaz.