Bir yöntemden birden çok dönüş değeri döndürmenin bir yolu: sınıf içinde dönüş değerini temsil eden put yöntemi. İyi bir tasarım mı?


15

Bir yöntemden 2 değer döndürmek gerekiyor. Benim yaklaşımım şöyledir:

  1. bu 2 değeri tutmak için kullanılacak 2 alanlı bir iç sınıf oluşturun
  2. yöntemi bu sınıfın içine koy
  3. sınıfı başlatır ve yöntemi çağırır.

Yöntemde değiştirilecek tek şey, sonunda bu 2 değeri örneğin alanlarına atamasıdır. Sonra bu değerleri o nesnenin alanlarına başvurarak ele alabilirim.

İyi bir tasarım mı ve neden?


Başka bir seçenek (muhtemelen kötü bir seçenek): bkz BitInteger[] java.math.BigInteger.divideAndRemainder(BitInteger val). Bir dizideki dönüş değerleri olarak 2 tamsayı döndürür.
earlNameless

Geri dönmek istediğiniz iki değer ne tür?
Tulains Córdova

Yanıtlar:


15

Bunu aşağıdaki satırlarda tartışacağım:

  • Metodunuz neden tam olarak birden fazla değer döndürüyor? Ne tür bir uyumdan bahsediyoruz - bu değerler aslında tek bir sınıftaki alanlar mı olmalı yoksa sadece aynı yöntemle tesadüfen geri dönüyorlar mı, yoksa başka türlü ilgisiz mi? Eğer ikinciyse, yöntemi iki yönteme ayırmayı düşünebilirsiniz. Düzenleme: kararınızı burada kullanın; bazen bir tür "tesadüfi" uyum en iyi seçenek olabilir. Diğer bir seçenek, bir çift veya demet yapı kullanmaktır, ancak OOP'de bunlar genellikle genel API'larda görülmez (bazı önemli istisnalar standart koleksiyonlar vb.).
  • Değerler bir sınıf oluşturmayı hak ederse, muhtemelen bir iç sınıf kullanılmamasını tavsiye ederim. İç sınıflar genellikle dışarıdan gizlenen dahili uygulama ayrıntıları olarak kullanılır. Bu sonucun kendi başına "tam gelişmiş" bir sınıf olmamasının bir nedeni var mı?
  • Veri tutma dışında, bu yeni sınıfa hangi işlemler uygulanabilir? Nesneye yönelik tasarımda, ilgili davranışın ilgili verilere yakın olmasını istersiniz (bu da sizin niyetiniz gibi görünüyor). Bahsettiğiniz yöntem bu sınıfta yaşamamalı mıdır?

Özetlemek gerekirse, bu "veri nesnesini" hem veri hem de davranış ile tam teşekküllü bir sınıfa dönüştürebilir miydim. Ek bir yorum olarak, durumu bir kez ayarlandığından sınıfı değişmez yapmak isteyebilirsiniz. Değişmez hale getirilmesi, yanlış ayarlanmasını veya daha sonra değiştirilmesini önlemeye yardımcı olacaktır (örneğin, alanlardan birini boş olarak ayarlayıp geçirme).

Düzenleme: Patkos Csaba'nın doğru bir şekilde işaret ettiği gibi, burada uygulanan prensip Tek Sorumluluk İlkesi'dir ( SRP ) - oluşturmaya çalıştığınız sınıfın gerçekten bir sorumluluğu olmalıdır ( değiştirme nedeni olarak tanımlanmıştır ). Bu tasarım kılavuzu, iki alanınızın tek bir sınıfa ait olup olmadığını anlamanıza yardımcı olmalıdır. Wikipedia örneğine sadık kalmak için, sınıfınız bir tür rapor olarak görülebilir, bu durumda SRP'ye uygundur, ancak daha fazla bilgi olmadan yorum yapmak zordur.


Bu cevabın genel fikrini kabul etsem de, birbiriyle yakından ilişkili iki veri parçasının birlikte hesaplandığı meşru durumlar vardır, ancak bunları programın başka herhangi bir yerinde birbirine bağlamanın bir anlamı yoktur. Böyle bir durumda geri dönmek için yeterince temiz olabilir Pair<OneClass, AnotherClass>. Bazı insanlar aynı fikirde değillerdi . Her durumda, Pairbir uygulama detayı olmalı ve asla genel bir API yönteminde görünmemelidir.
9000

@ 9000 katılıyorum; Aslında kelimenin tam anlamıyla bu durumda almayı düşündüğünü kastediyordum , yani yöntemi bölmek her zaman en iyi çözüm olmayabilir, bu yönde sadece kaba bir göstergedir. Bu satırlar boyunca bir düzenleme yapacağım.
Daniel B

1
İyi cevap. Ekleyeceğim tek şey Tek Sorumluluk İlkesi'ne (SRP) ( en.wikipedia.org/wiki/Single_responsibility_principle ) bir referanstır . İşaretlenirse, tartışılan yöntemin sadece basit bir SRP ihlali olması ve bir bölünmenin basit bir çözüm olması mümkündür. Deneyimlerime göre, bir yöntem 2 veya daha fazla değer döndürmek istediğinde, vakaların% 90'ında 2 yöntem vardır veya başka bir sınıf çıkarılmalıdır.
Patkos Csaba

@PatkosCsaba teşekkürler, dahil etmek için bir düzenleme yaptı. Normalde şeyleri birleştirme ve uyum açısından açıklamaya bağlı kalıyorum, ancak sanırım SOLID ilkeleri bu günlerde yaşamak için temel kurallar olarak görülüyor.
Daniel B

@DanielB: SOLID'i daha yüksek seviye ve muhtemelen anlaşılması kolay kavramlar olarak görüyorum. Kuplaj ve kohezyon hala temeldir, ancak daha düşük seviyededir. SOLID, ilkelerini açıklamak ve daha genel bir düzeyde sunmak için birleştirme ve uyumdan büyük ölçüde yararlanır.
Patkos Csaba

10

Python gibi diğer dillerde öne çıkan bir Tuple kavramı var.

Bu jenerikleştirilmiş sınıfın kolayca yeniden kullanılabilen bir örneği döndürülebilir:

public class TypedTuple<L, R> implements Serializable {
private static final long serialVersionUID = 1L;

  protected L left;
  protected R right;

  protected TypedTuple() {
    // Default constructor for serialization
  }

  public TypedTuple(L inLeft, R inRight) {
    left = inLeft;
    right = inRight;
  }

  public L getLeft() {
    return left;
  }

  public R getRight() {
    return right;
  }
}

2
Yapıcıda create()tür parametrelerini belirtmekten kaçınmak için genel bir statik yönteme sahip olmak bazen güzeldir . Ayrıca, bu sınıfı seçeceğini Pairyerine Tuplesadece değerler 2-dizilerini temsil edebilir verilen.
augurar

5

Görünüşe göre bu sınıf sorumluluğu başka bir sınıftan alıyor ve bu da bu tasarımın harika olmadığını düşündürüyor.

Birden çok değer döndüren bir yöntem için,

  • dönüş değerlerini içeren genel bir kapsayıcı (örneğin, bir Liste veya Harita) döndürme

veya

  • dönüş değeri için, yalnızca gerekli alanları + alıcıları + tüm alanları içeren bir yapıcıyı içeren bir Sınıf oluşturun

İkinci seçenek için örnek:

public Class FooBarRetval {
   private String foo;
   private int bar;

   public FooBarRetval (String foo, int bar) {
      this.foo = foo;
      this.bar = bar;
   }

   public String getFoo() {
      return foo;
   }

   public int getBar() {
      return bar;
   }
}

Alanları herkese açık hale getirmek, değerleri ayrı ayrı değiştirme seçeneğini ekler, ancak değerlerin açıkça bir ilişkisi vardır (aksi takdirde aynı yöntemle döndürülmeleri gerekmez). Bu özel durumda bu modelden vazgeçireceğim. Ancak asıl mesele, kamu ve özel niteliklerin tartışılmasının OP sorusu ile ilgisi yoktur ve aksi takdirde iyi bir cevapta son cümlenin hiçbir sebebini görmüyorum.
eşarp dolabı

İlki tercih edilmelidir.
Juanin

scarfridge: Puan alındı, son cümle kaldırıldı.
user281377

2
Herkese açık son alanları kullanın, erişimcilerle zaman kaybetmek için bir neden yok.
augurar


0

Kısa cevap: İki değer içeren bir dizi veya Liste döndürebilirsiniz.

Şahsen iki farklı yöntem yazardım.

int x = obj.getX();
int y = obj.getY();
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.