2012-10-01 14 views
19

Bazı şekilleri hareket ettiren bir arabirim (hareket) var.Arabirimi bir soyut sınıfa uzatın

interface Move { move(); } 
abstract class Shape : Move 

class Circle : Shape 
class Square : Shape 
class Triangle : Shape 

Benim şüphe Ben Şekiller ama sadece Çember ve Üçgen taşınacak gerekir hamle arayüzü olması gerekir, olduğunu, bu yüzden nasıl Meydanı'na arayüzü "kaldır" mı? Arayüzü Şekil'den kaldırmalı ve bunu Daire ve Üçgen'e manuel olarak eklemeliyim? Bununla kafam karıştı. Umarım birisi bana yardım eder. Sen kurulum gerekir

cevap

34

böyle dersleriniz:

interface IMovable { move(); } 
abstract class Shape : { } 

class Circle : Shape, IMovable { } 
class Square : Shape { } 
class Triangle : Shape, IMovable { } 

değil her şekil hareket ettirilebilir sonra Shape arabirimini uygulamak gerekir. Ayrıca, arayüzünüzü IMovable olarak yeniden adlandırdığımı unutmayın, bu büyük bir anlaşma değil, daha fazla kabul görüyor ve daha iyi bir adlandırma kuralı.

+4

Bu. "Bazı temel davranışları nasıl devralıyorum" sorusunun cevabı her zaman "ilk etapta bundan miras kalmaz". – KeithS

+0

@KeithS, bu doğru. Mirasın durdurulması mirasa bakmak için sadece ters yoldur. Öyleyse, bu, OP'nin diğer ilerleyiş yolunu düşünmesine yardımcı olacaktır. :) –

+4

@Mike, 'IMovable' hakkında ne dersiniz? – smartcaveman

27

Bir arabirimi bir devralma ağacından kaldıramazsınız.

İki soyut sınıfa gereksinim duyduğunuz model - Shape ve MovableShape.

interface IMove { move(); } 
abstract class Shape : {} 
abstract class MovableShape : IMove, Shape {} 

class Circle : MovableShape{} 
class Square : Shape{} 
class Triangle : MovableShape{} 
+3

Bu kabul edilen cevap olmalı. –

+3

@NadirSampaoli, siz __opinion__ usulüne uygun bir şekilde not düştünüz, ama bu çok öznel bir sohbete dönüşeceğinden emin olun. Unutulmaması gereken bir şey de, bu cevabı __I + 1'ledi çünkü doğru bir karardı. –

+3

@Mike Özür dilerim, aslında benim yorum sesim kalın; "Bence" diye eklemeliydim. –

3

Genel olarak arayüzler, sınıflar ve OO'nun arkasındaki fikirlere daha aşina olmalısınız. Anlatmaya çalıştığınız şey şudur:

  • Her şekil hareket ettirilebilir.
  • A Kare bir şekildir.
  • Ancak bir Kare taşınamaz.

Bu, anlamsızdır. Yani sınıf tasarımınızı ayarlamanız gerekiyor. Her şekil hareket ettirilebilir, Şekil (ve Kare) Taşı uygulamalıdır, ya da her şekil hareket ettirilemez, sonra Şekil Taşı uygulamamalıdır.

interface IMove { move(); } 
abstract class Shape { } 

class Circle : Shape, IMove { } 
class Square : Shape { } 
class Triangle : Shape, IMove { } 
3

bu deneyin.

public abstract class Shape : IMove 
{ 
    public virtual void Move() 
    { 
     throw new NotSupportedException(); 
    } 
} 

Yani günün sonunda, "Bir hareketli şekli taşımak için nasıl kendi uygulamasını sağlamalıdır" "Herhangi bir şekil hareketli olabilir" ama. Son olarak, aynı şekilde hareket eden bir sürü şekil olduğunu hayal edelim. Shape.Move sanal yöntemini geçersiz kılan Shape türetilen bir DefaultMovableShape özet sınıfı oluşturursunuz.

public abstract class DefaultMovableShape 
{ 
    public override void Move() 
    { 
      // Do stuff 
    } 
} 
2

Diğer seçenek sadece Shape sınıfında IMove.Move yöntemini uygulamak olabilir ve varsayılan olarak bir NotSupportedException atmak:

+0

Bu işe yaramazsa, bunu öneriyorum 'Move' işlevine ilişkin spesifikasyonunuz," Move "un altta yatan nesne için geçerli olmadığı durumda bir istisna atabileceği arabirim katmanında açıkça belirtilmediği sürece. Elbette, bu noktada, ara yüzün neden uygulandığını ve muhtemelen tasarım konusuna sahip olmanız gerektiğini sorgulamanız gerekir (kabul edilen cevaba bakınız). – Anthony

+0

@Anthony Kabul ediyorum. Sadece bir seçenek vermek istedim. Kabul edilen cevabın bunu yapmanın doğru yolu olduğunu düşünmek için nedenler olduğuna inanıyorum, ama benimki de, bazı durumlarda işi yapabilir. Sorunu nasıl düşündüğünüze bağlıdır: "bir şekil hareket edemez" veya "bir şekil hareket edebilir". –

+0

@Anthony Yorumunuzu iki kez kontrol ettim. Bu ifade 'Shape' sınıfındaki belgelerinde veya 'IMove' birinde olmalıdır. Şekil "hareket edebilir" çünkü bir Şekil "nasıl hareket edeceği" nin bir uygulamasını sağlayabilir. Bu yüzden, taşınamayan bir Şekli taşımaya çalışıyorsanız, bu Şekil "hareket etmeyi desteklemiyor". –

2

En iyi cevap, bu sınıflar için kullanım durumunun ve ortamın ne olacağına bağlı olacaktır. Bir uygulama veya çerçeve geliştiren bir ekibin parçası olarak, bu ekip tarafından kullanılan tasarım kalıplarının benimsenmesi, diğerlerinin kodunuzu benimsemesini ve sürdürmesini kolaylaştıracağı için 'mükemmel' bir çözüm aramaya tercih edilebilir.

Bu sınıfların kullanılmasını ve genişletilmesini nasıl beklediğiniz de önemlidir. Gelecekte 'Kare'nin hareket etmesi gerekecek mi?Bir Şekil'nin hareketliliği her zaman statik mi, yoksa dinamik bir özellik olarak daha kullanışlı olabilir mi? Taşı(), Şekiller olmayan sınıflar için herhangi bir değere sahip mi?

public abstract class Shape 
{ 
    public bool isMovable() 
    { 
     return false; 
    } 

    public virtual void Move() 
    { 
     if (!isMovable() { 
      throw new NotSupportedException(); 
     } else { 
      throw new BadSubclassException(); 
     } 
    } 
} 

Sizin alt sınıfları daha sonra statik veya dinamik davranışı sağlamanız isMovable geçersiz kılabilir ve ayrıca bu kadar uzun dokümantasyon yapar gibi, değiştirilmiş veya zamanla sınıflandırma yapılabilir: taşınabilirliktir dinamik bir özellik olarak yararlı olabilir, bunu düşünün isMoveable öğesinin her zaman Taşı seçeneğinden önce gelmesi gerekir. Varsayılan davranış, ilgili tasarım kalıplarını nasıl uyguladıklarına bağlı olarak, kodunuzu kullanmayı beklediğiniz diğer kişilerin beklentilerine dayanmalıdır.

Bu kararları vermenin zorluğuna iyi bir örnek, koleksiyon sınıflarının mutabilitesinin farklı çerçevelerde nasıl evrildiğinin tarihine bakılarak bulunabilir. Değişken sınıfların (kümeler, diziler, sözlükler vb.) Temel sınıf olduğu, alt sınıflarda ve aynı zamanda ters olarak uygulanan değişmezlik içeren tasarımlar olmuştur. Her iki yaklaşımın yanı sıra dinamik bir yaklaşım için geçerli argümanlar vardır, ancak bir çerçeve kullanıcısı için en önemli faktör tutarlılık, çünkü doğru olan şey, kullanımı kolay olan ve güvenliği sağlayan şeydir. ve performans tehlikeye girmez.

İlgili konular