Google , çok iyi olduğunu düşündüğüm bir cevapla benzer bir soru getirdi . Aşağıda alıntı yaptım.
Burada bağladığım Cook makalesinde anlatılan başka bir ayrım var.
Soyutlamayı uygulamanın tek yolu nesneler değildir. Her şey bir nesne değildir. Nesneler, bazı kişilerin prosedürel veri soyutlaması olarak adlandırdığı bir şey uygular. Soyut veri türleri farklı bir soyutlama biçimi uygular.
İkili yöntemleri / işlevleri düşündüğünüzde önemli bir fark görünür. Yordamsal veri soyutlama (nesneler) ile, Int set arabirimi için şöyle bir şey yazabilirsiniz:
interface IntSet {
void unionWith(IntSet s);
...
}
Şimdi IntSet'in iki uygulamayı düşünün, diyelim ki listelerle desteklenir, diğeri daha verimli bir ikili ağaç yapısı ile desteklenir:
class ListIntSet implements IntSet {
void unionWith(IntSet s){ ... }
}
class BSTIntSet implements IntSet {
void unionWith(IntSet s){ ... }
}
UnionWith öğesinin bir IntSet argümanı alması gerektiğine dikkat edin. ListIntSet veya BSTIntSet gibi daha belirgin bir tür değil. Bu, BSTIntSet uygulamasının girdisinin bir BSTIntSet olduğunu varsayamayacağı ve bu gerçeği verimli bir uygulama sağlamak için kullanamayacağı anlamına gelir. (Kontrol etmek için bazı çalışma süresi türü bilgileri kullanabilir ve varsa daha verimli bir algoritma kullanabilir, ancak yine de bir ListIntSet'ten geçirilebilir ve daha az verimli bir algoritmaya geri dönmesi gerekir).
Bunu, imza veya başlık dosyasında aşağıdakine benzer bir şey yazabileceğiniz ADT'lerle karşılaştırın:
typedef struct IntSetStruct *IntSetType;
void union(IntSetType s1, IntSetType s2);
Bu arayüze karşı program yapıyoruz. Özellikle, tür soyut bırakılır. Ne olduğunu bilmiyorsun. Daha sonra bir BST uygulamamız var ve daha sonra somut bir tür ve operasyonlar sağlıyor:
struct IntSetStruct {
int value;
struct IntSetStruct* left;
struct IntSetStruct* right;
}
void union(IntSetType s1, IntSetType s2){ ... }
Şimdi sendika aslında hem s1 hem de s2'nin somut temsillerini biliyor, bu yüzden verimli bir uygulama için bundan faydalanabilir. Ayrıca liste destekli bir uygulama yazabilir ve bunun yerine bağlantı kurmayı seçebiliriz.
C (ish) sözdizimi yazdım, ancak düzgün şekilde yapılan soyut veri türleri için örneğin Standart ML'ye bakmalısınız (burada aslında bir programın birden fazla ADT uygulamasını kabaca türleri niteleyerek kullanabilirsiniz: BSTImpl. IntSetStruct ve ListImpl.IntSetStruct, diyelim)
Bunun tersi, prosedürel veri soyutlamasının (nesneler) eskilerinizle çalışan yeni uygulamaları kolayca tanıtmanıza izin vermesidir. örneğin, kendi özel LoggingIntSet uygulamanızı yazabilir ve bir BSTIntSet ile birleştirebilirsiniz. Ama bu bir değiş tokuş: ikili yöntemler için bilgilendirici türleri kaybedersiniz! Genellikle arayüzünüzde bir ADT uygulamasından daha fazla işlevsellik ve uygulama ayrıntısı ortaya çıkarmak zorunda kalırsınız. Şimdi sadece Cook denemesini yeniden yazıyormuşum gibi hissediyorum, gerçekten okuyun!
Buna bir örnek eklemek istiyorum.
Cook, soyut bir veri türünün bir örneğinin C'deki bir modül olduğunu önerir. Aslında, C'deki modüller bilgi gizlemeyi içerir, çünkü bir başlık dosyası yoluyla dışa aktarılan genel işlevler ve olmayan statik (özel) işlevler vardır. Ayrıca, genellikle yapıcılar (örn. List_new ()) ve gözlemciler (ör. List_getListHead ()) vardır.
Diyelim ki, LIST_MODULE_SINGLY_LINKED ADT adlı bir liste modülünün önemli bir noktası, modülün işlevlerinin (örn. List_getListHead ()), girilen verilerin herhangi bir "eşdeğenin aksine LIST_MODULE_SINGLY_LINKED yapıcısı tarafından oluşturulduğunu varsaymasıdır. "bir listenin uygulanması (örn. LIST_MODULE_DYNAMIC_ARRAY). Bu, LIST_MODULE_SINGLY_LINKED işlevlerinin, uygulamalarında belirli bir temsili (örneğin, tek bağlantılı bir liste) varsayabileceği anlamına gelir.
LIST_MODULE_SINGLY_LINKED, LIST_MODULE_DYNAMIC_ARRAY ile LIST_MODULE_DYNAMIC_ARRAY ile etkileşime giremedi, çünkü LIST_MODULE_SINGLY_LINKED yapıcısı ile LIST_MODULE_SINGLY_M_NUMA__SAYAN_BİLGİSİNİ yalnızca bir liste için bir atandı.
Bu, soyut cebirden iki farklı grubun birlikte çalışamayacağı şekle benzer (yani, bir grubun bir öğesinin ürününü başka bir grubun bir öğesiyle alamazsınız). Bunun nedeni, grupların grubun kapanma özelliğini almasıdır (bir gruptaki öğelerin ürünü grupta olmalıdır). Bununla birlikte, iki farklı grubun aslında başka bir G grubunun alt grupları olduğunu kanıtlayabilirsek, G grubunun ürününü, iki grubun her birinden bir tane olmak üzere iki eleman eklemek için kullanabiliriz.
ADT'leri ve nesneleri karşılaştırma
Cook, ADT'ler ve nesneler arasındaki farkı kısmen ifade sorununa bağlar. Kabaca söylemek gerekirse, ADT'ler genellikle işlevsel programlama dillerinde uygulanan genel işlevlerle birleştirilirken, nesneler arabirimlerden erişilen Java "nesneleri" ile birleştirilir. Bu metnin amaçları için, genel bir işlev bazı ARGS bağımsız değişkenlerini ve bir TYPE türünü (ön koşul) alan bir işlevdir; TYPE temel alınarak uygun işlevi seçer ve ARGS (post-condition) ile değerlendirir. Hem genel fonksiyonlar hem de nesneler polimorfizm uygular, ancak genel fonksiyonlarda, programcı jenerik fonksiyonun koduna bakmadan jenerik fonksiyon tarafından yürütülecek olan BİLDİRİCİ BİLGİLERİ. Öte yandan nesnelerle, programcılar nesnenin koduna bakmadıkça, programcı nesnenin bağımsız değişkenleri nasıl işleyeceğini bilmez.
Genellikle ifade problemi "çok fazla temsilim var mı?" vs. "çok az temsili olan birçok fonksiyonum var" İlk durumda, kod temsili olarak düzenlenmelidir (özellikle Java'da en yaygın olanıdır). İkinci durumda, kod fonksiyonlara göre düzenlenmelidir (yani, tek bir genel fonksiyonun birden fazla temsili ele alması).
Kodunuzu temsile göre düzenlerseniz, daha fazla işlevsellik eklemek istiyorsanız, bu işlevi nesnenin her gösterimine eklemek zorunda kalırsınız ; bu anlamda işlevsellik ekleme "katkı maddesi" değildir. Kodunuzu işlevselliğe göre düzenlerseniz, fazladan bir gösterim eklemek istiyorsanız - her nesneye temsili eklemek zorunda kalırsınız ; bu anlamda "katkı maddesi" değil temsiller eklemek.
ADT'lerin nesnelere göre avantajı
İşlev eklemek ek bir şeydir
Performans için bir ADT'nin temsili bilgisinden faydalanmak veya ADT'nin bir önkoşul verildiğinde bazı son koşulları garanti edeceğini kanıtlamak mümkündür. Bu, ADT'lerle programlamanın doğru şeyleri doğru sırayla yapmakla ilgili olduğu anlamına gelir (önkoşulları ve sonkoşulları "hedef" sonrası koşula doğru birleştirmek).
Nesnelerin ADT'lere göre avantajları
Katkı maddesine temsiller ekleme
Nesneler etkileşime girebilir
Bir nesne için öncesi / sonrası koşullarını belirlemek ve bunları ADT'lerde olduğu gibi birbirine zincirlemek mümkündür. Bu durumda, nesnelerin avantajları, (1) arayüzü değiştirmeden temsillerin değiştirilmesinin kolay olması ve (2) nesnelerin birlikte çalışabilmesidir. Bununla birlikte, bu, OOP'un amacını smalltalk anlamında yener. (bkz. "Alan Kay'ın OOP versiyonu)
Dinamik dağıtım OOP'un anahtarıdır
Şimdi nesneye yönelik programlama için dinamik dağıtımın (yani geç bağlama) gerekli olduğu açıktır. Bu, prosedürleri belirli bir temsili varsaymayan jenerik bir şekilde tanımlamak mümkündür. Python'da somut - nesne yönelimli programlama kolaydır, çünkü bir nesnenin yöntemlerini belirli bir temsili varsaymayacak şekilde programlamak mümkündür. Bu nedenle python'un Java gibi arayüzlere ihtiyacı yoktur.
Java'da sınıflar ADT'lerdir. ancak, uyguladığı arabirimden erişilen bir sınıf bir nesnedir.
Zeyilname: Alan Kay'ın OOP versiyonu
Alan Kay, nesnelere açıkça "cebir familyaları" diye değinmiştir ve Cook, ADT'nin bir cebir olduğunu ileri sürmektedir. Dolayısıyla Kay muhtemelen bir nesnenin bir ADT ailesi olduğu anlamına geliyordu. Yani bir nesne, Java arabirimini karşılayan tüm sınıfların toplanmasıdır.
Ancak Cook tarafından boyanmış nesnelerin resmi Alan Kay'ın vizyonundan çok daha kısıtlayıcı. Nesnelerin bir ağdaki bilgisayarlar veya biyolojik hücreler gibi davranmasını istedi. Fikir, programlamaya en az bağlılık ilkesini uygulamaktı - böylece, yüksek düzey katmanlar kullanılarak kullanılarak bir ADT'nin düşük düzey katmanlarını değiştirmek kolaydır. Bu resim göz önünde bulundurulduğunda, Java arayüzleri çok kısıtlayıcıdır, çünkü bir nesnenin mesajın anlamını yorumlamasına ve hatta tamamen görmezden gelmesine izin vermezler .
Özetle, Kay için nesnelerin ana fikri, onların bir cebir ailesi (Cook tarafından vurgulandığı gibi) oldukları değildir . Bunun yerine, Kay'ın ana fikri, büyük (ağdaki bilgisayarlar) içinde çalışan bir modeli küçük olana (bir programdaki nesneler) uygulamaktı.
edit: Kay'ın OOP sürümünde bir başka açıklama: Nesnelerin amacı, açıklayıcı bir ideale yaklaşmaktır. Nesneye ne yapacağını söylemeliyiz - prosedürel programlama ve ADT'lerde olduğu gibi mikro yönetimin durumunun nasıl olduğunu söylememeliyiz. Burada , burada , burada ve burada daha fazla bilgi bulabilirsiniz .
edit: Alan Kay'ın OOP tanımını burada çok ama çok iyi bir şekilde buldum .