Class anahtar kelimesi olmadan “nesne yönelimli” programlamayı uygulayabilir misiniz?


29

Diyelim ki bir bankada "hesap" soyutlama yapmak istiyoruz. İşte functionPython'da bir nesne kullanarak bir yaklaşım :

def account():
    """Return a dispatch dictionary representing a bank account.

    >>> a = account()
    >>> a['deposit'](100)
    100
    >>> a['withdraw'](90)
    10
    >>> a['withdraw'](90)
    'Insufficient funds'
    >>> a['balance']
    10
    """
    def withdraw(amount):
        if amount > dispatch['balance']:
            return 'Insufficient funds'
        dispatch['balance'] -= amount
        return dispatch['balance']
    def deposit(amount):
        dispatch['balance'] += amount
        return dispatch['balance']
    dispatch = {'balance': 0,
                'withdraw': withdraw,
                'deposit': deposit}
    return dispatch

Tip soyutlamasını kullanarak başka bir yaklaşım daha var (örneğin, classPython'da anahtar kelime):

class Account(object):
    """A bank account has a balance and an account holder.

    >>> a = Account('John')
    >>> a.deposit(100)
    100
    >>> a.withdraw(90)
    10
    >>> a.withdraw(90)
    'Insufficient funds'
    >>> a.balance
    10
    """



    def __init__(self, account_holder):
        self.balance = 0
        self.holder = account_holder

    def deposit(self, amount):
        """Add amount to balance."""
        self.balance = self.balance + amount
        return self.balance

    def withdraw(self, amount):
        """Subtract amount from balance if funds are available."""
        if amount > self.balance:
            return 'Insufficient funds'
        self.balance = self.balance - amount
        return self.balance

Öğretmenim, classanahtar kelimeyi tanıtıp bize şu kurşun noktalarını göstererek "Nesneye yönelik programlama" konusunu başlattı :

Nesne yönelimli programlama

Modüler programları düzenlemek için bir yöntem:

  • Soyutlama engelleri
  • İleti geçişi
  • Bilgi ve ilgili davranışları bir araya getirmek

İlk yaklaşımın yukarıdaki tanımı yerine getirmek için yeterli olacağını düşünüyor musunuz? Evetse, classnesne yönelimli programlama yapmak için neden anahtar kelimeye ihtiyacımız var ?


2
Katılmana sevindim. =) Python'u tam bir cevap verecek kadar iyi bilmeme rağmen, Javascript'te OOP yapmanın tipik yolunun tanımladığınız "işlev nesnesi" ile aynı olduğunu bilmek ilginizi çekebilir (aynı zamanda prototip mirasımız olsa da) Her nesnenin her kopyasının ayrı kopyaları yerine nesnelerin yöntemleri "paylaşmasına" izin verir; Python'un classda benzer bir optimizasyon yaptığını varsayarım ).
Ixrec

Ayrıntılı bir cevap istiyorsanız, başka bir soru sormalı veya sohbet odasına katılmalısınız, ancak kısa cevap (temel prototip mirasını, dizileri vb. Tamamen görmezden gelirseniz); çoğu JS nesnesi, dizge tuşlarının keyfi değerlere ilişkin sözlüklerinden başka bir şey değildir. foo.bar()genellikle aynıdır foo['bar']()ve nadir durumlarda ikinci sözdizimi aslında yararlıdır.
Ixrec


8
Bu, OOP hakkında temel bir anlayışa giden yolda gerçekten önemli bir sorudur. İlgileniyorsanız, dilin OOP bölümlerinden hiçbirine güvenmeden JavaScript'te basit bir nesne sistemi oluşturduğum bir blog yazımı okuyabilirsiniz . İlk örnekte önemli bir eksiklik var: Yazacağın yerde object['method'](args), Python nesneleri aslında bunun eşdeğerini yapıyor object['method'](object, args). Bu, bir temel sınıf bir çocuk sınıfındaki yöntemleri çağırdığında, örneğin Strateji Örüntüsünde geçerli olur.
amon

13
Diğerlerinin de belirttiği gibi, bu OOP ile ilgili algısal bir sorudur. Ancak bu fırsatı, gerçek bankaların banka hesaplarını nasıl temsil ettiği hiç bir şey olmadığını unutmayın. Bankalar, borçlandırdığınızda ve kredi kullandığınızda değişebilen değişken bir "hesap" nesnesine sahip değildir; Onlar sadece yazma işlem listesine sahipler ve sonra bakiyeyi işlem listesinden hesaplıyorlar. İyi bir alıştırma olarak, bu mekanizmayı çeşitli dillerde uygulamaya çalışın.
Eric Lippert

Yanıtlar:


66

Tebrikler! Nesne oryantasyonunun özel programlama dili desteği olmadan yapılabileceği bilinen gerçeğini yeniden keşfettiniz. Temel olarak, bu klasik ders kitabındaki nesnelerin Scheme'de tanıtıldığı şekildedir . Scheme'nin bir classanahtar kelimeye veya bir tür eşdeğerine sahip olmadığını ve sınıfları bile olmadan nesneler oluşturulabileceğini unutmayın.

Bununla birlikte, nesne yönelimli paradigma o kadar başarılıydı ki birçok dil - ve Python istisna değildir - bunun için yerleşik destek sağlıyordu. Bu, geliştiricilerin paradigmayı kullanmalarını kolaylaştırmak ve bu dil için standart bir nesne yönlendirme biçimi sağlamak içindir. Temel olarak, birçok dilin bir fordöngü sağlamasının nedeni aynıdır , ancak whilebir veya iki ek kod satırı içeren bir döngü kullanılarak taklit edilebilse de - kullanım kolaylığı .


“Bu dile standart bir nesne yönelimi sağlamak için” Orada bir JavaScript eleştirisi duyuyor muyum? ;)
jpmc26

1
@ jpmc26: bilerek değil. Ve görünüşe göre JavaScript'te nesnelerin nasıl oluşturulduğuna dair genel kabul görmüş standartlar var.
Doc Brown

@overexchange: Sormanız gereken bir sorunuz mu var?
Doktor Brown

1
@overexchange: OOP'ın ne anlama geldiği tartışmalı, farklı düşünce okulları var, ancak SICP tanımı hemen hemen sorunuzdaki 3 mermi noktasından biri. Bu kesinlikle soyutlamalar oluşturmakla ilgilidir, ancak 2. ve 3. noktaları unutmayınız. Evet, OOP konsepti "durum değişikliğini" içerir, fakat aynı zamanda "değişmez nesneler" (Java veya C #, Python'daki string sınıfı gibi) kavramını da sağlar bazı değişken ve bazı değişken veri türlerine de sahiptir). Ve sorunuzdaki ilk örneğiniz, ikinci örneğinizin yanı sıra bu tanımı doğrular.
Doc Brown

2
@overexchange: bu Alain Kay'ın nesne yönelimi tanımına (küçük konuşma dilinin mucidi) geri döner. Bu stackoverflow.com/questions/2347973/… eski SO makalesinde kapsamlı bir cevap bulacaksınız . IMHO "SICP anlamında" nesneler arasında geçen mesaj "sadece bir nesnenin iç verilerine doğrudan, sadece" tanımlanmış bir iletişim protokolü "yoluyla erişim anlamına gelmez. Python gibi OO dillerinde bu sadece "bir nesnenin yöntemini çağırın" anlamına gelebilir.
Doktor Brown

13

İlk tanımın, öğretmeninizin belirttiği üç puanı sağladığına katılıyorum. Class anahtar kelimesine hiçbir şey için ihtiyacımız olduğunu sanmıyorum . Kapakların altında, veriyle çalışmak için farklı veri türleri ve fonksiyonlara sahip bir veri yapısından başka bir nesne nedir? Tabii ki, fonksiyonlar da veridir.

Daha da ileri gideceğim ve nesne yönelimli programlama yapmanın dilinizin sağladığı anahtar kelimelere o kadar bağımlı olmadığını söyleyebilirim , dilerseniz C'de nesne yönelimli programlama yapabilirsiniz! Aslında, linux çekirdeği bu teknikleri kullanır.

Buradaki class anahtar kelimesinden çıkartabileceğiniz şey, dilin kutudan bu tür bir yapı için destek sağlamasıdır ve işlevselliği kendiniz yeniden uygulamak için tüm kasnaklardan geçmenize gerek yoktur (ki bu oldukça eğlenceli bir görevdir). kendisi!). Alacağınız tüm sözdizimsel şekerden bahsetmiyorum bile.


mirastan ne haber? Gerçek zamanlı olarak alt tipler / süper tipler için çok mu önem veriyoruz? İlk yaklaşımım bunu eğlendirmeyebilir !!
aşırı değişim

5
Kalıtım, OOP için hiçbir şekilde gerekli değildir. Kalıtımı ilk örneğinizde de uygulayabilirsiniz. Çok da "temiz" değil, aynı şekilde mümkün olabilir.
Zavior

3
@Zavior bu yorum bana VB6 hakkında düşündürüyor. Kalıtım olmadan nesne yönelimli gerçekten de, daha az açık kod yazmayı sağlar.
RubberDuck

1
@overexchange Bunu düşündüğünüz zaman, miras tamamen sınıflar arasında ortak kod / davranış paylaşımı ile ilgilidir. Hiçbir şey, her zaman bu kodu tekrar etmenizi engelleyemez. Yine de korumak için süper korkunç olurdu.
Kalıtımın

1
@Zavior En temel şekliyle "alt sınıflama", "burada yüksek dereceli gönderme ve veri alma işlevini döndürmeden önce burada tanımladığım bir soyutlamadır (burada" sınıf "gibi davranacağız) ha), ThisParentFoo "tarafından belirtilen" üst sınıf "gönderme ve veri alma işlevini başlat. Gerçekten hepsi bu. Çok sayıda mirastan kurtulma söz konusu olduğunda, gerçekte hala hepsi bu kadardır, ancak “elmas problemini” ortaya çıkardığınız ihtirasla, bu yüzden çoklu mirasın berbat olmasıdır.
zxq9

9

Tabi ki yapabilirsin!

Kendi kendini programlama dili, her şeyin bir nesne olduğu ve sınıf duygusu ya da hiç olmadığı bir dinamik prototip tabanlı nesne yönelimli dildir. Prototipik nesneler fikrine ve nesnelerin nasıl yaratılacağının şablonları olarak sınıflar yerine klonlama fikrine odaklanmıştır.

Daha fazla bilgi için http://www.selflanguage.org/ adresini kontrol etmelisiniz . Bence çok ilginç ve eğer OOP'u seviyorsanız, o kadar yaygın olmayan bir şeyi kontrol etmek iyi bir fikir.


0

Her zaman değil: dile bağlıdır. Bunu Python'da yapma yeteneğini kanıtladınız, ancak (sorunuz Python etiketine rağmen dilden agnostik ise) tüm diller bunu yapamaz. Örneğin, Java çoğunlukla yapamaz. Ana içeren sınıfı yok sayarak, sınıf içinde anahtar sözcük olmadan ana içinde tanımlanmış bir nesnede rasgele yöntemler / alanlar tanımlamanın yolu yoktur. Anonim sınıflar mevcut olmasına rağmen, bir arayüze ihtiyaç duyarlar ve arayüzde tanımlananlar dışında hiçbir ortak üyeye sahip olamazlar. Özel arayüzleri tanımlamak mümkün olsa da, onlar için anonim sınıflar yapmak mümkün olsa da, bu sadece bir sınıf kullanmaktan tamamen aynıdır (ancak daha az kullanışlı).

Doktor Brown'un çok iyi bir cevabı var, fakat yapmaya çalıştığım nokta, çözümünüze hiç izin vermeyecek en az bir dil olduğundan emin olduğum.


Başlangıç ​​olarak, "Nesneye yönelik programlama" kavramını öğrenmek için, evet, dille agnostik olmaya çalışıyorum. Sanırım "Doc Brown" aynı satırlarda cevap verdi, bana herhangi bir dil sözdizimi ile ilgisi olmayan sicp text-chap3'ü okuduğunu söyledi.
aşırı değişim

Cevabımı doğrulamak için sınıfları kesinlikle kullanmak isteyen bir dili isimlendirmek isterdim. Ama ben sadece birkaç dil biliyorum ve ne yazık ki Java bir çalışmama izin veriyor. C ++ 'ın yapıları vardır ve Javascript açık olarak gösterdiklerinize izin verir. Kesinlikle yapılı olduklarını duyduğum için Smalltalk ve Eiffel’in ders alması gerektiğinden şüpheleniyorum.
SkySpiral7

Doktor Brown olarak, şemayı kullanarak oop öğrenseydim, bu soruyu sormazdım. Ne yazık ki, öğrendiğim SICP kursunun sürümü python kullanıyor.
aşırı değişim

1
Her geçerli Java programı classanahtar kelimeyi içermelidir, bu yüzden sürpriz olmaz. Ancak kendi nesne sisteminizi Java'nın nesne sisteminin üstüne kesinlikle uygulayabilirsiniz, ancak neden böyle bir şey yapmak istediğinizi bilmiyorum.
Brian Gordon

1. Java bu konuda gerçekten özeldir, çünkü özel veri yapıları oluşturmak için kullanılabilecek diğer tüm anahtar kelimeleri basitçe çöpe atmıştır. Bildiğim diğer dillerin hemen hemen hepsinde kayıtlar veya kapanışlar var. 2. Hatta java, sen yapabilirsiniz bir diziden inşa edilmiş bir bellek programlamak. Ve yapabilirsiniz kullanarak, o içinde nesne yönelimini uygulamak classdil sınıflarında Fonksiyonlarınızı koymak gerektirir çünkü sadece anahtar kelime. Tabii ki, bu son derece teorik, ama Java'da bile yerleşik sınıflar olmadan Nesne Yönlendirme yapabilirsiniz!
cmaster

0

Öğretmeninizin tanımı, onu işe yarayan ve benzersiz kılan nesne yönelimli programlamanın en önemli noktasını tamamen özlüyor. "Mesaj geçme", Smalltalk halkı tarafından hayal edilen bir saçmalıktır ve her yerde denendiği bir başarısızlıktır. OOP'un gerçek gücü Liskov'un ikame edilmesi olarak bilinen bir şeydir ve kavram tanımlanması ve anlaşılması oldukça basit olsa da, temeldeki uygulama dil düzeyinde destek olmadan doğru bir şekilde yapmanın imkansız olduğu kadar karmaşıktır.

Liskov ikamesi fikri, kodunuzun belirli bir türden bir değişken beklediği herhangi bir yerde, bu türden türetilen herhangi bir türü kabul edebilmesi ve türetilen türün ayrıntılarını bilmeden hala düzgün çalışabilmesi gerektiğidir.

Örneğin, GUI çerçeveleri her yerde Liskov yerine kullanmaktadır. ControlÇizim, yeniden boyutlandırma ve kullanıcı girdisine yanıt verme gibi temel eylemleri bilen bir arabirimi tanımlayan "herhangi bir kontrolü" temsil edebilecek bir temel sınıfa sahip olma eğilimindedirler . Bir kontrole tıklarsanız, UI çerçevesi Clickne tür bir kontrole dikkat etmenize gerek kalmadan kontrole bir metot çağırır ve daha sonra kontrolün tıklamayı kendi sınıfı için uygun şekilde ele almasına izin verir. Bir Buttonkontrol TextBox, yalnızca bir örnek vermek için, bir kontrolden tıklandığında tamamen farklı bir şey yapmalıdır .

Bu yüzden evet, yukarıda açıklanan iç içe geçmiş fonksiyon numaralarını kullanarak nesnelere benzer bir şey yaratabilirsiniz, ancak miras ve Liskov ikame yöntemini bu şekilde alamadığınız için, gerçek OOP için son derece sınırlı bir ikamedir.


C dilinde 'struct parent {}' ve sonra 'struct child {struct parent * ptr;}' diyemiyorum? Bu, oop dışı dil sözdiziminde miras değil midir?
abartı değiştirme

@overexchange: Bu, OO'yu taklit etme girişimidir, ancak derleyici bir tanesini diğeriyle değiştirmenize izin vermez . (Bir geçemez child*bir alan bir işleve parent*. En az bir typecast olmadan, bağımsız değişken olarak) Ve daha da kötüsü, C yapılar kendilerine bağlı yöntemleri olamaz ve hiçbir destek yok sanal yöntemlerle, Liskov ikamesinin sihrini neyin işe yaramasına neden oldu, bu yüzden elinizle VMT'leri inşa etmeniz gerekiyor.
Mason Wheeler

1
Linux çekirdeği, hepsi dil desteği olmadan manuel olarak kodlanması gereken birkaç OO tekniğinin emülasyonunu kullanır. Bu, Linux olan Linus Yasası'nın liberal bir uygulaması ile dengelenen böcekler için birçok fırsat yaratır. Evet, bunu yapmak mümkün - Turna denkliği bunu kanıtlıyor - ama benim açımdan dil desteği olmadan haklı olmanın son derece zor olduğunu düşünüyorum. Ayrıca, neden soru Python'dayken C ile ilgili tüm bu sorular? C'de iç içe geçmiş fonksiyonlar hilesini ilk önce yapmak mümkün değildir.
Mason Wheeler

1
@overexchange Java bir "programcılar cenneti" ne zamandır?
Brandin

1
İleti geçen gelmiştir değil Smalltalk, Erlang, hatta Java tarzı OOP sistemlerinde bir başarısızlık burada "işlev çağrısı" (eski Java pazarlama VS bir evre kuyruğuna sahip QT'ın sinyalleri & yuvaları terimi kullanarak "mesaj" den "mesaj" anlamına gelir farklı bir şey "yöntem çağrısı" anlamına geldiğinde). Mesajlar! = Fonksiyon çağrıları. Orijinal mesajlaşma sadece başarılı değil, aynı anda ve aynı anda güçlü sistemler yazmayı bildiğimiz tek yol gibi görünüyor. Bu, 'class' anahtar sözcüğü olmadan Java stili OOP'yi uygulamak için diktir. Bu olabilir yapılabilir. Her zaman kullanışlı değildir . Mesajlaşma meselenin yanında.
zxq9

-1

Hızlı Kısa Cevap

Evet, Programcılar Nesneye Yönelik Programlamayı "Sınıflar" olmadan uygulayabilirler.

Uzun Sıkıcı Kapsamlı Açıklayıcı Cevap

Birçok programcının aklına gelen ilk kavram olan "Nesne Yönelimi" nin çeşitli varyasyonları vardır, "Sınıflar" dır.

Evet, Programcılar Nesneye Yönelik Programlamayı "Sınıflar" olmadan uygulayabilir, ancak her programlama dilinin özellikleri ve sınırlamaları ile sınırlıdır.

Gönderiniz Python olarak etiketlendi , bu nedenle, soru başlığınız "Python'da Sınıfsız Nesne Yönelimli Programlamanın Nasıl Uygulanacağı" gibi olabilir.

Şu anda Javascript'in "Prototyping" veya Visual Basic "Based" gibi diğer çeşitlerinden veya "functors" kullanarak "Pure C" deki öykünmeden tanımlamak için "Object and Class Oriented Programming" (Nesne ve Sınıf Odaklı Programlama) ifadesini kullanıyorum.

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.