2016-04-09 11 views
3

Ben Smalltalk (Squeak) yeni bir kullanıcı (aslında bir kursa çalışıyordum). - Daha iyi bu yazmak için bir yol yokturSmalltalk içinde bir yöntemi geri yükleme

isEqual:givenRec 
    self a = givenRec a 
    ifTrue: [ 
     self b = givenRec b 
     ifTrue: [ 
      ^true 
     ]. 
     ^false 
    ]. 
    self b = givenRec a 
    ifTrue: [ 
     self a = givenRec b 
     ifTrue: [ 
      ^true 
     ]. 
     ^false 
    ]. 
    ^false 

sorum şu: Bir dikdörtgen şöyle bir verilen dikdörtgen eşittir eğer bir yöntem kontrol etmek zorunda? Daha kompakt olması için?

ayrıca neden kendi iç yöntemlere sahip örnekVariableNames olan a'a bakamıyorum? Yardımın için teşekkürler!

DÜZENLEME:

bu sınıf nasıl tanımlandığını geçerli:

MyShape subclass: #MyTriangle 
    instanceVariableNames: 'a b c' 
    classVariableNames: '' 
    poolDictionaries: '' 
    category: 'Ex2' 

MyShape basitçe Object kaynaklanmaktadır ve ilgisi yoktur.

cevap

4

Bunu daha kompakt hale getirebilirsiniz, evet. İlk olarak, #ifTrue:'un yanı sıra, #ifFalse: ve #ifTrue:ifFalse:'un yanı sıra, eğer değilse-sonra-sonra-ve-sonra-sonra-başka etkisi de vardır.

Ama aynı zamanda, zaten bir mantıksal AND koşulunu, böylece kullanmayın neden vardır:

isEqual: givenRec 

    (self a = givenRec a and: [self b = givenRec b]) 
     ifTrue: [^ true]. 
    (self b = givenRec a and: [self a = givenRec b]) 
     ifTrue: [^ true]. 
    ^false 

Ayrıca #ifTrue:ifFalse:

isEqual: givenRec 

    (self a = givenRec a and: [self b = givenRec b]) 
     ifTrue: [^ true] 
     ifFalse: [^ (self b = givenRec a and: [self a = givenRec b])] 

ile, bütün açıklamada etrafında dönüşünü yapabilirsiniz:

Ancak ifTrue: [true] biraz artık,kullanalım

isEqual: givenRec 

    ^(self a = givenRec a and: [self b = givenRec b]) or: 
     [self b = givenRec a and: [self a = givenRec b]] 

Güzel ve tatlı, biz de oldukça kolay mantıksal yapısını görmek. (iki mantıksal ifadedeki benzerlikleri ve farklılıkları belirtmek için ortak biçimlendirme stillerinden ayrıldığımı unutmayın). Şimdi yalnızca bir tane geri ^ sahip

, örneğin değişken soru için hiçbir #ifTrue:…


: Eğer yaptığımız gibi sınıftaki bazı örnek değişkenleri tanımlarken

, içeri anlamıyla kullanabilirsiniz kodunuzu bunlara erişmek için:

Object subclass: #Contoso 
    instanceVariableNames: 'things' 
    classVariableNames: '' 
    poolDictionaries: '' 
    category: 'Examples' 
isThingPlusThreeSameAs: anObject 

    ^thing + 3 = anObject 

Ama genellikle tutucuların yaygın erişimcileri denilen ve belirleyiciler yoluyla örnek değişkenleri başvurmak için daha iyidir.Sen tarayıcıda bir sınıfın (“... devamı” yoluyla) manuel olarak yazmak ya ikinci bağlam menüsünün 'inst var erişimci oluşturmak' menü öğesi kullanmak zorunda:

Bu forma

thing 

    ^thing 
thing: anObject 

    thing := anObject 

ait bir erişim yöntemine üretecektir ve tasarımlarıyla bunları kullanabilir İkincisi çok iyi okumak değil çünkü bu

isThingPlusThreeSameAs: anObject 

    ^self thing + 3 = anObject 
+0

sayesinde kullanışlı olduğu meta programlama vardır, ben sorumu düzenlenebilir - – Infested

+0

başka bir soru @Tobias sınıf tanımını eklendi - i nasıl çizerim ekranda bir dikdörtgen iki kenarları uzunlukları verilen? – Infested

+0

Yani sınıf iyi görünüyor, Şimdi gerçekten karşılaştırma için vardı koduna bağlıdır. ~~ Dikdörtgen çizerek için cevabım – Tobias

0

gibi r yöntemleri Ben seçici #equals: yerine #isEqual: kullanıyorum arada

equals: aTriangle 
    a = aTriangle a ifFalse: [^false]. 
    b = aTriangle b ifFalse: [^false]. 
    ^c = aTriangle c 

Not olarak yöntemini yazılı olurdu İngilizce (o #isEqualTo: olmuştu olsaydı, ama #equals: kısadır).

Buraya ekleyeceğim başka bir açıklama, yeni bir karşılaştırma seçicisi eklemek yerine #= yeniden tanımlamanız olabilir.

= aTriangle 
    self class = aTriangle class ifFalse: [^false]. 
    a = aTriangle a ifFalse: [^false]. 
    b = aTriangle b ifFalse: [^false]. 
    ^c = aTriangle c 
sınıf çek nedeni #= yani sağlam olduğundan emin olmaktır

, bir MessageNotUnderstood istisna işaret etmez: Bu durumda, ancak, ek birkaç şeyden dikkat etmek zorunda . Başka şey her zaman (yeniden) de (yeniden) olmalıdır #= tanımlamak t1 hash = t2 hash zaman t1 = t2 o şekilde #hash tanımlamak olmasıdır. Örneğin #hash için bu öneriyi iyi biri değil, ama bu iyi #hash fonksiyonlarını yazma sorunu görüşmek üzere yer olmadığını

hash 
    ^(a hash + b hash + c hash) hash 

Not. Sipariş

equals: aTriangle 
    | sides | 
    self = aTriangle ifTrue: [^true]. 
    sides := Set with: a with: b with: c. 
    (sides includes: aTriangle a) ifFalse: [^false]. 
    (sides includes: aTriangle b) ifFalse: [^false]. 
    ^(sides includes: aTriangle c) 

ilk karşılaştırma sırası aynı olduğunda Set kaçınarak yöntemi hızlandırmak olduğunu fark etmez zaman

GÜNCELLEME

İşte benim sürümüdür.

+0

bir vertex fark ettiğinde erken dönüşü kullanamazsınız, çünkü siparişi görmezden gelen köşe noktalarını karşılaştırmak ister, (a, b, c) = (c , b, a) –

+0

@ CarlosE.Ferro Teşekkürler, cevabı güncelledim. –

+0

İki farklı eşitlik kavramından hoşlanmıyorum, biri # ile sipariş edilen köşeli # ve diğer sette #equalsTo: .. –

0

Muhtemelen bu gibi yazmak gerekir ama durumlar bu

isEqual: givenRec 
    #(a b c) do: [ :selector | 
    (self perform: selector) = (givenRec perform: selector) ifFalse: [ 
     ^false]]. 
    ^true 
İlgili konular