Reputation: 287
My goal is to create a button when you click on a disabled button it will print a specific message. But if you don't use the enable feature it will not ask you for the specific message in the constructor parameter.
Let say we have this class
class Button {
final String label;
final bool enable;
final String disableMessage;
Button(
this.label, {
bool? enable,
String? disableMessage,
}) : assert(enable == null || disableMessage != null),
enable = enable ?? true,
disableMessage = disableMessage ?? '';
}
I tried with an assert and conditional value but when I call it
Button('name', enable: false);
it doesn't display any error because this is only an assert.
I'm looking a way to have this behavior
Button('name'); // Good
Button('name', enable: false); // Error displayed
Button('name', disabledMessage: 'Button disabled'); // Error displayed
Button('name', enable: false, disabledMessage: 'Button disabled'); // Good
Is it a proper way to have conditional required parameter when another is used ?
Upvotes: 3
Views: 3375
Reputation: 89926
it doesn't display any error because this is only an assert.
assert
s throw an AssertionError
if you compile with assertions enabled (e.g. debug builds). This is appropriate for logical errors (i.e., the programmer is at fault for violating an API contract) such as yours.
However, if you'd prefer for an error to be thrown in all build types, then you could do so explicitly. For example:
void alwaysAssert(bool condition, String message) {
if (!condition) {
throw AssertionError(message);
}
}
class Button {
...
Button(
this.label, {
bool? enable,
String? disabledMessage,
}) : enable = enable ?? true,
disabledMessage = disabledMessage ?? '' {
// Note that the function parameters shadow the member variables, so
// `enable` an `disabledMessage` here are the local function parameters.
alwaysAssert(
enable == null || disabledMessage != null, 'Your error message');
}
Note that the above copies the logic from your existing assert
and therefore will throw an error if you do Button('name', enable: true)
. I don't know if that's really what you want. It also fails to fail for the Button('name', disabledMessage: 'Button disabled')
case. I think you actually want:
Button(
this.label, {
this.enable = true,
String? disabledMessage,
}) : disabledMessage = disabledMessage ?? '' {
alwaysAssert(!enable == (disabledMessage != null), 'Your error message');
}
But alternatively consider making the API simpler for callers by deducing enable
:
class Button {
final String label;
final String? _disabledMessage;
Button(
this.label, {
String? disabledMessage,
}) : _disabledMessage = disabledMessage;
bool get enable => _disabledMessage == null;
String get disabledMessage => _disabledMessage ?? '';
}
or by making separate constructors:
class Button {
final String label;
final bool enable;
final String disabledMessage;
Button(this.label)
: enable = true,
disabledMessage = '';
Button.disabled(this.label, this.disabledMessage) : enable = false;
}
Upvotes: 1