Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3.x: Merge as() into to() #6514

Merged
merged 2 commits into from
Jun 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion docs/What's-different-in-3.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,56 @@ TBD.

### API signature changes

#### as() and to() operators

In 2.x, the `to()` operator used the generic `Function` to allow assembly-time conversion of flows into arbitrary types. The drawback of this
approach was that each base reactive type had the same `Function` interface in their method signature,
thus it was impossible to implement multiple converters for different reactive types within the same class.
To work around this issue, the `as` operator and `XConverter` interfaces have been introduced
in 2.x, which interfaces are distinct and can be implemented on the same class. Changing the signature of `to` in 2.x was not possible due
to the pledged binary compatibility of the library.

From 3.x, the `as()` methods have been removed and the `to()` methods now each work with their respective `XConverer` interfaces:

- `Flowable.to(Function<Flowable<T>, R>)` is now `Flowable.to(FlowableConverter<T, R>)`
- `Observable.to(Function<Observable<T>, R>)` is now `Observable.to(ObservableConverter<T, R>)`
- `Maybe.to(Function<Flowable<T>, R>)` is now `Maybe.to(MaybeConverter<T, R>)`
- `Single.to(Function<Flowable<T>, R>)` is now `Maybe.to(SingleConverter<T, R>)`
- `Completable.to(Function<Completable, R>)` is now `Completable.to(CompletableConverter<R>)`
- `ParallelFlowable.to(Function<ParallelFlowable<T>, R)` is now `ParallelFlowable.to(ParallelFlowableConverter<T, R>)`

If one was using these methods with a lambda expression, only a recompilation is needed:

```java
// before
source.to(flowable -> flowable.blockingFirst());

// after
source.to(flowable -> flowable.blockingFirst());
```

If one was implementing a Function interface (typically anonymously), the interface type, type arguments and the `throws` clause have to be adjusted

```java
// before
source.to(new Function<Flowable<Integer>, Integer>() {
@Override
public Integer apply(Flowable<Integer> t) throws Exception {
return t.blockingFirst();
}
});

// after
source.to(new FlowableConverter<Integer, Integer>() {
@Override
public Integer apply(Flowable<Integer> t) {
return t.blockingFirst();
}
});
```

TBD.

- as() merged into to()
- some operators returning a more appropriate Single or Maybe
- functional interfaces throws widening to Throwable
- standard methods removed
Expand Down
43 changes: 9 additions & 34 deletions src/main/java/io/reactivex/Completable.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import io.reactivex.internal.operators.maybe.*;
import io.reactivex.internal.operators.mixed.*;
import io.reactivex.internal.operators.single.*;
import io.reactivex.internal.util.ExceptionHelper;
import io.reactivex.observers.TestObserver;
import io.reactivex.plugins.RxJavaPlugins;
import io.reactivex.schedulers.Schedulers;
Expand Down Expand Up @@ -1182,29 +1181,6 @@ public final Completable andThen(CompletableSource next) {
return RxJavaPlugins.onAssembly(new CompletableAndThenCompletable(this, next));
}

/**
* Calls the specified converter function during assembly time and returns its resulting value.
* <p>
* <img width="640" height="751" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Completable.as.png" alt="">
* <p>
* This allows fluent conversion to any other type.
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code as} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
* <p>History: 2.1.7 - experimental
* @param <R> the resulting object type
* @param converter the function that receives the current Completable instance and returns a value
* @return the converted value
* @throws NullPointerException if converter is null
* @since 2.2
*/
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final <R> R as(@NonNull CompletableConverter<? extends R> converter) {
return ObjectHelper.requireNonNull(converter, "converter is null").apply(this);
}

/**
* Subscribes to and awaits the termination of this Completable instance in a blocking manner and
* rethrows any exception emitted.
Expand Down Expand Up @@ -2578,27 +2554,26 @@ private Completable timeout0(long timeout, TimeUnit unit, Scheduler scheduler, C
}

/**
* Allows fluent conversion to another type via a function callback.
* Calls the specified converter function during assembly time and returns its resulting value.
* <p>
* <img width="640" height="751" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Completable.to.png" alt="">
* <p>
* This allows fluent conversion to any other type.
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code to} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
* @param <U> the output type
* @param converter the function called with this which should return some other value.
* <p>History: 2.1.7 - experimental
* @param <R> the resulting object type
* @param converter the function that receives the current Completable instance and returns a value
* @return the converted value
* @throws NullPointerException if converter is null
* @since 2.2
*/
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final <U> U to(Function<? super Completable, U> converter) {
try {
return ObjectHelper.requireNonNull(converter, "converter is null").apply(this);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
throw ExceptionHelper.wrapOrThrow(ex);
}
public final <R> R to(@NonNull CompletableConverter<? extends R> converter) {
return ObjectHelper.requireNonNull(converter, "converter is null").apply(this);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/io/reactivex/CompletableConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import io.reactivex.annotations.*;

/**
* Convenience interface and callback used by the {@link Completable#as} operator to turn a Completable into another
* Convenience interface and callback used by the {@link Completable#to} operator to turn a Completable into another
* value fluently.
* <p>History: 2.1.7 - experimental
* @param <R> the output type
Expand Down
38 changes: 6 additions & 32 deletions src/main/java/io/reactivex/Flowable.java
Original file line number Diff line number Diff line change
Expand Up @@ -5646,30 +5646,6 @@ public final Single<Boolean> any(Predicate<? super T> predicate) {
return RxJavaPlugins.onAssembly(new FlowableAnySingle<T>(this, predicate));
}

/**
* Calls the specified converter function during assembly time and returns its resulting value.
* <p>
* This allows fluent conversion to any other type.
* <dl>
* <dt><b>Backpressure:</b></dt>
* <dd>The backpressure behavior depends on what happens in the {@code converter} function.</dd>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code as} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
* <p>History: 2.1.7 - experimental
* @param <R> the resulting object type
* @param converter the function that receives the current Flowable instance and returns a value
* @return the converted value
* @throws NullPointerException if converter is null
* @since 2.2
*/
@CheckReturnValue
@BackpressureSupport(BackpressureKind.SPECIAL)
@SchedulerSupport(SchedulerSupport.NONE)
public final <R> R as(@NonNull FlowableConverter<T, ? extends R> converter) {
return ObjectHelper.requireNonNull(converter, "converter is null").apply(this);
}

/**
* Returns the first item emitted by this {@code Flowable}, or throws
* {@code NoSuchElementException} if it emits no items.
Expand Down Expand Up @@ -16878,20 +16854,18 @@ public final Flowable<Timed<T>> timestamp(final TimeUnit unit, final Scheduler s
* <dt><b>Scheduler:</b></dt>
* <dd>{@code to} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
* <p>History: 2.1.7 - experimental
* @param <R> the resulting object type
* @param converter the function that receives the current Flowable instance and returns a value
* @return the value returned by the function
* @return the converted value
* @throws NullPointerException if converter is null
* @since 2.2
*/
@CheckReturnValue
@BackpressureSupport(BackpressureKind.SPECIAL)
@SchedulerSupport(SchedulerSupport.NONE)
public final <R> R to(Function<? super Flowable<T>, R> converter) {
try {
return ObjectHelper.requireNonNull(converter, "converter is null").apply(this);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
throw ExceptionHelper.wrapOrThrow(ex);
}
public final <R> R to(@NonNull FlowableConverter<T, ? extends R> converter) {
return ObjectHelper.requireNonNull(converter, "converter is null").apply(this);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/io/reactivex/FlowableConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import io.reactivex.annotations.*;

/**
* Convenience interface and callback used by the {@link Flowable#as} operator to turn a Flowable into another
* Convenience interface and callback used by the {@link Flowable#to} operator to turn a Flowable into another
* value fluently.
* <p>History: 2.1.7 - experimental
* @param <T> the upstream type
Expand Down
47 changes: 11 additions & 36 deletions src/main/java/io/reactivex/Maybe.java
Original file line number Diff line number Diff line change
Expand Up @@ -2279,27 +2279,6 @@ public final Maybe<T> ambWith(MaybeSource<? extends T> other) {
return ambArray(this, other);
}

/**
* Calls the specified converter function during assembly time and returns its resulting value.
* <p>
* This allows fluent conversion to any other type.
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code as} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
* <p>History: 2.1.7 - experimental
* @param <R> the resulting object type
* @param converter the function that receives the current Maybe instance and returns a value
* @return the converted value
* @throws NullPointerException if converter is null
* @since 2.2
*/
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final <R> R as(@NonNull MaybeConverter<T, ? extends R> converter) {
return ObjectHelper.requireNonNull(converter, "converter is null").apply(this);
}

/**
* Waits in a blocking fashion until the current Maybe signals a success value (which is returned),
* null if completed or an exception (which is propagated).
Expand Down Expand Up @@ -3579,28 +3558,24 @@ public final <U> Maybe<U> ofType(final Class<U> clazz) {
}

/**
* Calls the specified converter function with the current Maybe instance
* during assembly time and returns its result.
* Calls the specified converter function during assembly time and returns its resulting value.
* <p>
* This allows fluent conversion to any other type.
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code to} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
* @param <R> the result type
* @param convert the function that is called with the current Maybe instance during
* assembly time that should return some value to be the result
*
* @return the value returned by the convert function
* <p>History: 2.1.7 - experimental
* @param <R> the resulting object type
* @param converter the function that receives the current Maybe instance and returns a value
* @return the converted value
* @throws NullPointerException if converter is null
* @since 2.2
*/
@CheckReturnValue
@NonNull
@SchedulerSupport(SchedulerSupport.NONE)
public final <R> R to(Function<? super Maybe<T>, R> convert) {
try {
return ObjectHelper.requireNonNull(convert, "convert is null").apply(this);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
throw ExceptionHelper.wrapOrThrow(ex);
}
public final <R> R to(@NonNull MaybeConverter<T, ? extends R> converter) {
return ObjectHelper.requireNonNull(converter, "converter is null").apply(this);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/io/reactivex/MaybeConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import io.reactivex.annotations.*;

/**
* Convenience interface and callback used by the {@link Maybe#as} operator to turn a Maybe into another
* Convenience interface and callback used by the {@link Maybe#to} operator to turn a Maybe into another
* value fluently.
* <p>History: 2.1.7 - experimental
* @param <T> the upstream type
Expand Down
35 changes: 6 additions & 29 deletions src/main/java/io/reactivex/Observable.java
Original file line number Diff line number Diff line change
Expand Up @@ -5076,27 +5076,6 @@ public final Single<Boolean> any(Predicate<? super T> predicate) {
return RxJavaPlugins.onAssembly(new ObservableAnySingle<T>(this, predicate));
}

/**
* Calls the specified converter function during assembly time and returns its resulting value.
* <p>
* This allows fluent conversion to any other type.
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code as} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
* <p>History: 2.1.7 - experimental
* @param <R> the resulting object type
* @param converter the function that receives the current Observable instance and returns a value
* @return the converted value
* @throws NullPointerException if converter is null
* @since 2.2
*/
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final <R> R as(@NonNull ObservableConverter<T, ? extends R> converter) {
return ObjectHelper.requireNonNull(converter, "converter is null").apply(this);
}

/**
* Returns the first item emitted by this {@code Observable}, or throws
* {@code NoSuchElementException} if it emits no items.
Expand Down Expand Up @@ -13913,19 +13892,17 @@ public final Observable<Timed<T>> timestamp(final TimeUnit unit, final Scheduler
* <dt><b>Scheduler:</b></dt>
* <dd>{@code to} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
* <p>History: 2.1.7 - experimental
* @param <R> the resulting object type
* @param converter the function that receives the current Observable instance and returns a value
* @return the value returned by the function
* @return the converted value
* @throws NullPointerException if converter is null
* @since 2.2
*/
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final <R> R to(Function<? super Observable<T>, R> converter) {
try {
return ObjectHelper.requireNonNull(converter, "converter is null").apply(this);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
throw ExceptionHelper.wrapOrThrow(ex);
}
public final <R> R to(@NonNull ObservableConverter<T, ? extends R> converter) {
return ObjectHelper.requireNonNull(converter, "converter is null").apply(this);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/io/reactivex/ObservableConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import io.reactivex.annotations.*;

/**
* Convenience interface and callback used by the {@link Observable#as} operator to turn an Observable into another
* Convenience interface and callback used by the {@link Observable#to} operator to turn an Observable into another
* value fluently.
* <p>History: 2.1.7 - experimental
* @param <T> the upstream type
Expand Down
Loading