blob: f81e3e0cc99695ab95d6380628e404a7fa1d7f17 [file] [view]
---
name: webrtc/provide-default-methods-for-new-java-interface-methods
description: When evolving public Java interfaces, provide default implementations for backward compatibility, and omit removal TODOs on permanent optional capability fallbacks
rubric: readability
severity: blocking
---
**Rule.** When adding new methods, callbacks, or listener events to existing
public Java interfaces, provide `default` implementations (such as an empty body
`{}` for void observer/callback methods, or a sensible fallback return value)
rather than declaring them as abstract methods without bodies. Additionally,
when providing default implementations for interface methods that represent
optional features or hardware-specific capabilities, do not add a `TODO` to
remove the default body or make the method abstract/pure virtual, as optional
capabilities are intended to have permanent fallbacks rather than temporary
migration shims.
**Why.** Adding abstract methods to existing public Java interfaces breaks
source and binary compatibility for external implementers and downstream
applications during SDK updates. Providing default implementations allows new
methods and callbacks to land safely without forcing immediate subclass
modifications. Furthermore, default methods for optional capabilities serve as
permanent fallbacks for implementations lacking the feature; adding removal
TODOs on optional APIs creates false migration churn by suggesting that all
subclasses must eventually implement the method.
## Examples
Bad:
```cpp
public interface AudioDeviceObserver {
// Bad: Adding abstract method to existing public interface breaks downstream implementers.
@CalledByNative("AudioDeviceObserver")
void onRemoveTrack(RtpReceiver receiver);
// Bad: Optional capability default is marked with a removal TODO.
/** TODO(b/279738239): Remove default implementation. */
default boolean setNoiseSuppressorEnabled(boolean enabled) {
return false;
}
}
```
Good:
```cpp
public interface AudioDeviceObserver {
// Good: Default empty body preserves backward compatibility for existing implementers.
@CalledByNative("AudioDeviceObserver")
default void onRemoveTrack(RtpReceiver receiver) {}
// Good: Permanent default fallback for optional capability without a removal TODO.
default boolean setNoiseSuppressorEnabled(boolean enabled) {
return false;
}
}
```