Tamam, bir arkadaşım programlamada "arayüzün" ne anlama geldiğini ileri geri söylüyor.
Bir "arayüz" ün en iyi tanımı nedir.
Bana göre bir arayüz bir sınıfın bir planıdır, bu en iyi tanım mıdır?
Tamam, bir arkadaşım programlamada "arayüzün" ne anlama geldiğini ileri geri söylüyor.
Bir "arayüz" ün en iyi tanımı nedir.
Bana göre bir arayüz bir sınıfın bir planıdır, bu en iyi tanım mıdır?
Yanıtlar:
Arayüz, geliştirmede en fazla aşırı yüklü ve kafa karıştırıcı terimlerden biridir.
Aslında bir soyutlama ve kapsülleme kavramıdır. Belirli bir "kutu" için, bu kutunun " girişlerini" ve "çıkışlarını" bildirir . Yazılım dünyasında, bu genellikle kutuda çağrılabilen işlemler (argümanlarla birlikte) ve bazı durumlarda bu işlemlerin dönüş türleri anlamına gelir.
Yapmadığı şey, bu işlemlerin anlamlarının ne olduğunu tanımlamaktır, ancak bunları bildirime yakın olarak belgelemek (örneğin, yorumlar yoluyla) veya iyi adlandırma kurallarını seçmek sıradan (ve çok iyi bir uygulamadır). Yine de, bu niyetlerin yerine getirileceğine dair hiçbir garanti yoktur.
İşte bir benzetme: Kapalıyken televizyonunuza bir göz atın. Arayüzü, sahip olduğu düğmeler, çeşitli fişler ve ekrandır. Anlamsallığı ve davranışı, girişleri alması (örneğin, kablo programlama) ve çıkışlara (ekranda görüntü, ses vb.) Sahip olmasıdır. Ancak, prize takılı olmayan bir TV'ye baktığınızda, beklenen anlam bilginizi bir arayüze yansıtırsınız. Bildiğiniz tek şey, televizyonu prize taktığınızda patlayabilir. Ancak, "arayüzüne" dayanarak su girişi olmadığı için kahve yapmayacağını varsayabilirsiniz.
Nesne yönelimli programlamada, bir arabirim genellikle bu arabirime sahip bir sınıf örneğinin yanıt verebileceği yöntemler (veya mesajlar) kümesini tanımlar.
Karışıklığa katkıda bulunan şey, Java gibi bazı dillerde, dile özgü anlambilimiyle gerçek bir arayüzün olmasıdır. Örneğin Java'da, uygulaması olmayan bir yöntem bildirimleri kümesidir, ancak bir arabirim de bir türe karşılık gelir ve çeşitli yazım kurallarına uyar.
C ++ gibi diğer dillerde arayüzlere sahip değilsiniz. Bir sınıfın kendisi yöntemleri tanımlar, ancak sınıfın arayüzünü özel olmayan yöntemlerin bildirimleri olarak düşünebilirsiniz. C ++ 'ın nasıl derlendiği nedeniyle, gerçek uygulama olmadan sınıfın "arabirimine" sahip olabileceğiniz başlık dosyalarını alırsınız. Ayrıca saf sanal işlevlere sahip soyut sınıflarla Java arayüzlerini de taklit edebilirsiniz.
Bir arayüz, kesinlikle bir sınıf için bir plan değildir. Bir plan, bir tanıma göre "ayrıntılı bir eylem planıdır". Bir arayüz, bir eylem hakkında hiçbir şey vaat etmez! Karışıklığın kaynağı, çoğu dilde, bir dizi yöntemi tanımlayan bir arabirim türüne sahipseniz, onu uygulayan sınıfın aynı yöntemleri "yinelemesi" (ancak tanım sağlar), dolayısıyla arabirimin bir iskelet veya bir iskelet gibi görünmesidir. sınıfın ana hatları.
Şu durumu düşünün:
Bir zombi aniden size saldırdığında geniş, boş bir odanın ortasındasınız.
Silahın yok.
Neyse ki, yaşayan bir insan, odanın kapısında duruyor.
"Hızlı!" ona bağırıyorsun. "Bana zombiye vurabileceğim bir şey fırlat!"
Şimdi düşünün: Arkadaşınızın
tam olarak ne atmayı seçeceğini belirtmediniz (ne de umursamıyorsunuz) ;
... Ama şu sürece önemli değil:
It adlı bir şeyler olabilir atmış (Sana kanepe atmak olamaz)
Bu tutabileceğin bir şey (Umarım bir shuriken atmamıştır)
Bu, zombinin beynini kırmak için kullanabileceğiniz bir şey (Bu, yastık ve benzeri şeyleri dışlar)
Bir beyzbol sopası veya çekiç almanız fark etmez -
üç koşulunuzu yerine getirdiği sürece iyisinizdir.
Özetlersek:
Bir arayüz yazdığınızda, temel olarak "Bir şeye ihtiyacım var ..." diyorsunuz.
Arayüz, uygulayıcı veya kullanıcı olmanıza bağlı olarak uymanız veya vermeniz gereken bir sözleşmedir.
Planın kullanmak için iyi bir kelime olduğunu sanmıyorum. Bir plan size bir şeyi nasıl inşa edeceğinizi söyler. Bir arayüz özellikle size bir şeyi nasıl inşa edeceğinizi söylemekten kaçınır.
Bir arayüz, bir sınıfla nasıl etkileşim kurabileceğinizi, yani hangi yöntemleri desteklediğini tanımlar.
Bana göre bir arayüz bir sınıfın bir planıdır, bu en iyi tanım mıdır?
Hayır. Plan tipik olarak iç kısımları içerir. Ancak bir arayüz, tamamen bir sınıfın dışında görünen şeyle ilgilidir ... veya daha doğrusu, arayüzü uygulayan bir sınıflar ailesi.
Arayüz, sabitlerin yöntemlerinin ve değerlerinin imzalarından ve ayrıca arayüzü uygulayan sınıflar ve onu kullanan diğerleri arasında (tipik olarak gayri resmi) bir "davranışsal sözleşme" içerir.
Programlamada bir arayüz, bir nesnenin sahip olacağı davranışı tanımlar, ancak aslında davranışı belirtmez. Bu, belirli bir sınıfın bir şeyler yapabileceğini garanti edecek bir sözleşmedir.
Bu C # kodunu burada düşünün:
using System;
public interface IGenerate
{
int Generate();
}
// Dependencies
public class KnownNumber : IGenerate
{
public int Generate()
{
return 5;
}
}
public class SecretNumber : IGenerate
{
public int Generate()
{
return new Random().Next(0, 10);
}
}
// What you care about
class Game
{
public Game(IGenerate generator)
{
Console.WriteLine(generator.Generate())
}
}
new Game(new SecretNumber());
new Game(new KnownNumber());
Oyun sınıfı gizli bir numara gerektirir. Bunu test etmek için, gizli numara olarak kullanılacak olanı enjekte etmek istersiniz (bu ilkeye Kontrolün Ters Çevrilmesi adı verilir).
Oyun sınıfı, rastgele sayıyı gerçekte neyin yaratacağı konusunda "açık fikirli" olmak ister, bu nedenle kurucusunda "Generate yöntemi olan herhangi bir şey" soracaktır.
İlk olarak arayüz, bir nesnenin hangi işlemleri sağlayacağını belirtir. Sadece neye benzediğini içerir, ancak gerçek bir uygulama verilmez. Bu sadece yöntemin imzasıdır. Geleneksel olarak, C # arayüzlerinde bir I öneki bulunur. Sınıflar artık IGenerate Arayüzünü uygular. Bu, derleyicinin her ikisinin de bir int döndüren ve çağrılan bir yönteme sahip olduğundan emin olacağı anlamına gelir Generate
. Oyuna şimdi iki farklı nesne deniyor ve bunların her biri doğru arayüze sahip. Diğer sınıflar, kodu oluştururken bir hata üretebilir.
Burada, kullandığınız plan benzetmesini fark ettim:
Bir sınıf, genellikle bir nesnenin taslağı olarak görülür. Bir Arayüz, bir sınıfın yapması gereken bir şeyi belirtir, bu yüzden bunun bir sınıf için sadece bir taslak olduğu iddia edilebilir, ancak bir sınıfın mutlaka bir arayüze ihtiyacı olmadığı için, bu metaforun kırıldığını iddia ediyorum. Arayüzü bir sözleşme olarak düşünün. "İmzalayan" sınıfın sözleşmedeki hüküm ve koşullara uyması yasal olarak gerekli olacaktır (derleyici polisi tarafından zorunlu kılınacaktır). Bu, arayüzde belirtilenleri yapması gerektiği anlamına gelir.
Bu, Java veya C # ile olduğu gibi, bazı OO dillerinin statik olarak yazılmış doğasından kaynaklanmaktadır. Python'da ise başka bir mekanizma kullanılır:
import random
# Dependencies
class KnownNumber(object):
def generate(self):
return 5
class SecretNumber(object):
def generate(self):
return random.randint(0,10)
# What you care about
class SecretGame(object):
def __init__(self, number_generator):
number = number_generator.generate()
print number
Burada, sınıfların hiçbiri bir arabirim uygulamaz. Python bunu umursamaz, çünkü SecretGame
sınıf sadece geçirilen nesneyi çağırmaya çalışır. Nesne bir generate () yöntemine sahipse, her şey yolunda demektir. Olmazsa: KAPUTT! Bu hata derleme zamanında değil, çalışma zamanında, dolayısıyla muhtemelen programınız zaten konuşlandırılmış ve çalışırken görülecektir. Sen buna yaklaşmadan C # seni uyarırdı.
Bu mekanizmanın kullanılmasının nedeni, safça ifade edilir, çünkü OO dillerinde doğal olarak işlevler birinci sınıf vatandaş değildir. Gördüğünüz, gibi KnownNumber
ve SecretNumber
bir sayı oluşturmak için SADECE işlevleri içerir. İnsanın derslere gerçekten ihtiyacı yok. Python'da, bu nedenle, biri onları bir kenara atabilir ve işlevleri kendi başlarına seçebilir:
# OO Approach
SecretGame(SecretNumber())
SecretGame(KnownNumber())
# Functional Approach
# Dependencies
class SecretGame(object):
def __init__(self, generate):
number = generate()
print number
SecretGame(lambda: random.randint(0,10))
SecretGame(lambda: 5)
Bir lambda, "ilerledikçe sırayla" bildirilen bir işlevdir. Temsilci, C # 'da aynıdır:
class Game
{
public Game(Func<int> generate)
{
Console.WriteLine(generate())
}
}
new Game(() => 5);
new Game(() => new Random().Next(0, 10));
Ek not: Son örnekler Java 7'ye kadar bunun gibi mümkün değildi. Orada, bu davranışı belirlemenin tek yolu Arabirimlerdi. Bununla birlikte, Java 8 lambda ifadelerini tanıttı, böylece C # örneği çok kolay bir şekilde Java'ya dönüştürülebilir ( Func<int>
olur java.util.function.IntSupplier
ve =>
olur ->
).
Teknik olarak, bir arabirimi bir nesneyle etkileşime girmenin bir dizi yolu (yöntemler, özellikler, erişimciler ... kelime haznesi kullandığınız dile bağlıdır) olarak tanımlardım. Bir nesne bir arabirimi destekliyorsa / uyguluyorsa, bu nesneyle etkileşim kurmak için arabirimde belirtilen tüm yolları kullanabilirsiniz.
Anlamsal olarak, bir arayüz, ne yapıp yapamayacağınıza (örneğin, yöntemleri çağırabileceğiniz sıra) ve karşılığında, nasıl etkileşim kurduğunuza göre nesnenin durumu hakkında ne varsayabileceğinize dair kurallar da içerebilir. Irak.
Şahsen şablon gibi bir arayüz görüyorum. Bir arabirim foo () ve bar () yöntemlerinin tanımını içeriyorsa, bu arabirimi kullanan her sınıfın foo () ve bar () yöntemlerine sahip olduğunu bilirsiniz.
Bir Adamın (Kullanıcı veya Nesne) bazı işlerin yapılmasını istediğini düşünelim. Şirketlerle (uygulanan sınıflar kullanılarak oluşturulan gerçek dünya nesneleri) bir sözleşme yapacak olan bir aracı (Arayüz) ile iletişime geçecektir. Hangi şirketlerin uygulayacağı ve sonuç vereceği birkaç tür iş kendisi tarafından tanımlanacaktır. Her firma işi kendine göre uygulayacak ama sonuç aynı olacak. Bu Kullanıcı işini tek bir arayüz kullanarak yapacağı gibi. Arayüzün, uygulayan iç alt sistemler tarafından dahili olarak tanımlanacak birkaç komutla sistemlerin görünür bir parçası olarak hareket edeceğini düşünüyorum.
Bir arabirim, bir sınıftaki işlemleri içindeki uygulamadan ayırır. Bu nedenle, bazı uygulamalar birçok arayüz sağlayabilir.
İnsanlar bunu genellikle sınıfın yöntemlerinde bulunması gerekenler için bir "sözleşme" olarak tanımlarlar.
Kesinlikle bir plan değildir, çünkü bu aynı zamanda uygulamayı da belirleyecektir. Tam bir sınıf tanımının bir plan olduğu söylenebilir.
Bir arabirim, kendisinden miras alan bir sınıfın uygulaması gerektiğini tanımlar. Bu şekilde, birden çok sınıf bir arabirimden miras alabilir ve bu eylemsizlik nedeniyle,
daha fazla bilgi için bu http://msdn.microsoft.com/en-us/library/ms173156.aspx adresine bakın.
Bana göre arayüz, Java'da yaygın olarak ilişkilendirilen arayüzden daha geniş bir anlama sahiptir. "Arayüzü", bir modülün kontrol edilmesine / izlenmesine olanak tanıyan bazı ortak işlevlere sahip bir dizi kullanılabilir işlem olarak tanımlardım.
Bu tanımda, hem istemcinin bir modül olduğu programatik arayüzleri hem de insan arayüzlerini (örneğin GUI) kapsamaya çalışıyorum.
Diğerlerinin daha önce de söylediği gibi, bir arayüzün arkasında her zaman girdi ve çıktılar açısından bir sözleşme vardır. Arayüz, işlemlerin "nasıl" olduğuna dair hiçbir şey vaat etmiyor; yalnızca mevcut durum, seçilen işlem ve parametreleri göz önüne alındığında sonucun bazı özelliklerini garanti eder.
Yukarıdaki gibi, "sözleşme" ve "protokol" eşanlamlıları uygundur.
Arayüz, bir sınıf tarafından ifşa edilmesini bekleyebileceğiniz yöntem ve özellikleri içerir.
Dolayısıyla, bir sınıf arabirimi Cheetos Bag
uygularsa, a'nın tıpkı diğerleri gibi davranmasını Chip Bag
beklemelisiniz . (Yani, yöntemi ortaya çıkarın vb.)Cheetos Bag
Chip Bag
.attemptToOpenWithoutSpillingEverywhere()
Geleneksel Tanım - Arayüz, onu uygulayan sınıf tarafından uygulanması gereken yöntemleri belirten bir sözleşmedir.
Arayüzün Tanımı zamanla değişti. Arayüzün yalnızca yöntem bildirimlerine sahip olduğunu mu düşünüyorsunuz? Peki ya statik son değişkenler ve Java 5'ten sonraki varsayılan tanımlamalar ne olacak?
Arayüzler Java'ya çoklu Miras ile ilgili Diamond problemi nedeniyle tanıtıldı ve aslında yapmayı amaçladıkları şey bu.
Arayüzler, çoklu kalıtım probleminden kurtulmak için oluşturulmuş yapılardır ve soyut yöntemlere, varsayılan tanımlara ve statik son değişkenlere sahip olabilir.
İki sistemin iletişim kurduğu sınır.
Arayüzler, bazı OO dillerinin geçici çok biçimliliğe nasıl ulaştığıdır . Ad hoc polimorfizm, farklı türlerde çalışan aynı adlara sahip işlevlerdir.
Kısacası, bir arayüzün çözmeye çalıştığı temel problem, bir şeyi nasıl kullandığımızı, nasıl uygulandığından ayırmaktır. Ancak arayüzün bir sözleşme olmadığını düşünmelisiniz . Daha fazlasını buradan okuyun .