🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: pl.comp.lang.java
3 messages
3 total messages Started by Borneq Fri, 14 Mar 2014 07:05
Co gdy funkcja ma zwrócić dwie rzeczy?
#153993
Author: Borneq
Date: Fri, 14 Mar 2014 07:05
6 lines
1146 bytes
Na przykład TryPop pobierająca ze stosu czy kolejki ma zwrócić:
- element
- boolean czy udało się zwrócić, czy też struktura jest pusta
TryConvert- próbująca konwertować tekst na int czy real
W Pascalu obchodzi się to (nie jest to za elegancko) przez parametry 
będące referencjami czy wskaźnikami i zwracające wartość. A w Javie?
Re: Co gdy funkcja ma zwrócić dwie rzeczy?
#153994
Author: Arivald
Date: Fri, 14 Mar 2014 08:14
116 lines
4315 bytes
On 2014-03-14 08:05, Borneq wrote:
> Na przykład TryPop pobierająca ze stosu czy kolejki ma zwrócić:
> - element
> - boolean czy udało się zwrócić, czy też struktura jest pusta
> TryConvert- próbująca konwertować tekst na int czy real

Najprościej, jeśli element nie może być nullem, zwracaj element, jeśli 
null to się nie udało.

> W Pascalu obchodzi się to (nie jest to za elegancko) przez parametry
> będące referencjami czy wskaźnikami i zwracające wartość. A w Javie?

Można zasymulować przekazywanie przez referencję, np. tak:

public class ObjectHolder<T> {
     public T o;

     public ObjectHolder() {
         this.o = null;
     }

     public ObjectHolder(T o) {
         this.o = o;
     }
}

i użycie

ObjectHolder<Data> dataRef = new ObjectHolder<Data>();

if (someFunction(param1, param2, dataRef)) {
     do something(dataRef.o);
}



Ale to mało eleganckie, używam tylko w testach, kiedy nie chce mi się 
pisać specjalnych klas tylko do tego.

W rzeczywistym kodzie, możliwe rozwiązania:

1) Zwracasz Pair<T1, T2>, jeśli jest w bibliotece lub sobie dopisałeś. 
Android ma tą klasę. Jest równie prosta, kod na końcu posta.

2) Budujesz osobną, specjalizowaną klasę wyniku, POJO tyko z polami 
final, i ją zwracasz z funkcji.
Taką klasę zresztą można przekazywać poprzez parametr, wtefy wynik wyn 
kcji możesz użyć do zwrócenia boolean (udało się) lub kodu błędu 
(chociaż to lepiej się wyjątkami robi)

3) Budujesz osobną klasę realizującą tą funkcję, z której potem wyniki 
pobierasz getterami
Coś jak:

Calculation calc = new Calculation(param1, param2, param 3);
if (calc.getSuccess()) {
     something = calc.getResult1();
     other= calc.getResult2();
}

Może "Calulation" to nie najlepsza nazwa, ten konstrukt nadaje się do 
wywołań RPC / WebService, etc.


4) a jak nie przeszkadza Ci brak silnego typowania, zwróć kolekcję 
obiektów, np ArrayList - dostęp po indexie, lub HashMap - dostęp po 
kluczu. Ale takie programowanie może prowadzić do trudnych do 
debugowania błędów.


Implementacja immutable Pair, którą można używać w HashMapie (ma 
hashCode i equals).

public class Pair<A, B> {
   public final A first;
   public final B second;

   public Pair(A first, B second) {
     super();
     this.first = first;
     this.second = second;
   }

   public static <A, B> Pair <A, B> create(A a, B b) {
     return new Pair<A, B>(a, b);
   }

   public int hashCode() {
     int result = 17;
     if (first != null) result = 31 * result + first.hashCode();
     if (result != null) result = 31 * result + second.hashCode();
     return result;
   }

   public boolean equals(Object other) {
     if (other instanceof Pair) {
       Pair otherPair = (Pair) other;
       return (
         (this.first == otherPair.first || (this.first != null && 
otherPair.first != null && this.first.equals(otherPair.first)))
       &&
         (this.second == otherPair.second ||(this.second != null && 
otherPair.second != null && this.second.equals(otherPair.second)))
       );
     }

     return false;
   }

   public String toString() {
          return "(" + first + ", " + second + ")";
   }
}

-- 
Arivald
Re: Co gdy funkcja ma zwrócić dwie rzeczy?
#153995
Author: Piotr Rezmer
Date: Fri, 14 Mar 2014 08:30
23 lines
1870 bytes
Borneq pisze:
> Na przykład TryPop pobierająca ze stosu czy kolejki ma zwrócić:
> - element
> - boolean czy udało się zwrócić, czy też struktura jest pusta

Tutaj można też posilić się generacją wyjątku, np. 
EStructureEmptyException. Tyle że wtedy zmieniłbym nazwę funkcji z 
TryPop() na Pop().

A w przypadku gdy będziesz musiał zwrócić więcej obiektów, możesz 
umieścić ich tyle ile chcesz w pojedynczym obiekcie PopResponse. Podobne 
podejście stosuje się w szkieletach web services generowanych dla 
soapEncoding = documentLiteral. Ma to też swoją zaletę że używanie pary 
FunctionRequest/FunctionResponse upraszcza modyfikację kodów jeśli 
będziesz chciał dodać jakiś parametr w przyszłości. Tam gdzie go nie 
potrzebujesz nie będzie potrzeby wprowadzania jakiejkolwiek zmiany 
(inaczej niż w przypadku function( arg1, arg2, arg3, arg4 ) )


-- 
pozdrawiam
Piotr
XLR250&bmw_f650_dakar
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads