-
Notifications
You must be signed in to change notification settings - Fork 383
Add "base", "final" and "interface" modifiers #920
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
Conversation
@@ -14,7 +14,7 @@ import 'http.dart'; | |||
/// NOTE: [RetryClient] makes a copy of the request data in order to support | |||
/// resending it. This can cause a lot of memory usage when sending a large | |||
/// [StreamedRequest]. | |||
class RetryClient extends BaseClient { | |||
final class RetryClient extends BaseClient { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interface is identical to client. There is no reason to implement or extend this.
@@ -31,7 +31,7 @@ BaseClient createClient() { | |||
/// [BaseRequest.followRedirects], and [BaseRequest.maxRedirects] fields. It is | |||
/// also unable to stream requests or responses; a request will only be sent and | |||
/// a response will only be returned once all the data is available. | |||
class BrowserClient extends BaseClient { | |||
base class BrowserClient extends BaseClient { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interface is identical to Client
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this should be final
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could imagine people wanting to add methods to Client
implementations. Like:
class DownloadingBrowserClient extends BrowserClient {
Stream<UInt8List> downloadFile(Url) {
...
}
}```
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is usable as a skeleton/base class for people who might want to extend the interface, then I'd just make it open (no modifier).
The example you give shows exactly that: You forgot to put base
on DownloadingBrowserClient
, and the author of it might want to allow other implementations (for testing/mocking or genuinely considers it an interface worth implementing).
So, final
or open, only use base
for very particular cases where extending is fine, but inheriting implementation is essential (mainly existing code which calls private members on the type).
I expect very few base
modifiers, because of the transitive "must be base
" requirement. It can't be used for just "don't implement this interface, because it doesn't make sense". We don't have that, sadly. (Otherwise Object
would have that modifier, but it definitely cannot be base
.)
pkgs/http/lib/src/io_client.dart
Outdated
@@ -43,7 +43,7 @@ class _ClientSocketException extends ClientException | |||
} | |||
|
|||
/// A `dart:io`-based HTTP client. | |||
class IOClient extends BaseClient { | |||
base class IOClient extends BaseClient { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interface is identical to Client
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd make it final
or open.
There is no need to require extending subclasses to be base
.
pkgs/http/test/io/client_test.dart
Outdated
@@ -14,14 +14,14 @@ import 'package:test/test.dart'; | |||
|
|||
import '../utils.dart'; | |||
|
|||
class TestClient extends http.BaseClient { | |||
base class TestClient extends http.BaseClient { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interface is identical to Client
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class is in the test directory, so no need to give it a modifier unless one is required.
pkgs/http/test/io/client_test.dart
Outdated
@override | ||
Future<http.StreamedResponse> send(http.BaseRequest request) { | ||
throw UnimplementedError(); | ||
} | ||
} | ||
|
||
class TestClient2 extends http.BaseClient { | ||
base class TestClient2 extends http.BaseClient { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interface is identical to Client
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto. Just no modifier. It's not a public class, so we don't care what people can do with it.
pkgs/http/test/io/http_test.dart
Outdated
@@ -10,7 +10,7 @@ import 'package:test/test.dart'; | |||
|
|||
import '../utils.dart'; | |||
|
|||
class TestClient extends http.BaseClient { | |||
base class TestClient extends http.BaseClient { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interface is identical to Client
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also just a test class, so no modifier needed.
I didn't add |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The BaseClient
class is documented as "This is a mixin-style class" and it can be used as a mixin today, so I'd recommend making it a mixin class
.
LGTM without the base
s.
(The package could generally use some clean-up. A lot of the code seems overly complicated, and could use more modern features or just be optimized better.)
@@ -31,7 +31,7 @@ BaseClient createClient() { | |||
/// [BaseRequest.followRedirects], and [BaseRequest.maxRedirects] fields. It is | |||
/// also unable to stream requests or responses; a request will only be sent and | |||
/// a response will only be returned once all the data is available. | |||
class BrowserClient extends BaseClient { | |||
base class BrowserClient extends BaseClient { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is usable as a skeleton/base class for people who might want to extend the interface, then I'd just make it open (no modifier).
The example you give shows exactly that: You forgot to put base
on DownloadingBrowserClient
, and the author of it might want to allow other implementations (for testing/mocking or genuinely considers it an interface worth implementing).
So, final
or open, only use base
for very particular cases where extending is fine, but inheriting implementation is essential (mainly existing code which calls private members on the type).
I expect very few base
modifiers, because of the transitive "must be base
" requirement. It can't be used for just "don't implement this interface, because it doesn't make sense". We don't have that, sadly. (Otherwise Object
would have that modifier, but it definitely cannot be base
.)
pkgs/http/lib/src/io_client.dart
Outdated
@@ -43,7 +43,7 @@ class _ClientSocketException extends ClientException | |||
} | |||
|
|||
/// A `dart:io`-based HTTP client. | |||
class IOClient extends BaseClient { | |||
base class IOClient extends BaseClient { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd make it final
or open.
There is no need to require extending subclasses to be base
.
pkgs/http/test/io/client_test.dart
Outdated
@@ -14,14 +14,14 @@ import 'package:test/test.dart'; | |||
|
|||
import '../utils.dart'; | |||
|
|||
class TestClient extends http.BaseClient { | |||
base class TestClient extends http.BaseClient { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class is in the test directory, so no need to give it a modifier unless one is required.
pkgs/http/test/io/http_test.dart
Outdated
@@ -10,7 +10,7 @@ import 'package:test/test.dart'; | |||
|
|||
import '../utils.dart'; | |||
|
|||
class TestClient extends http.BaseClient { | |||
base class TestClient extends http.BaseClient { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also just a test class, so no modifier needed.
pkgs/http/test/io/client_test.dart
Outdated
@override | ||
Future<http.StreamedResponse> send(http.BaseRequest request) { | ||
throw UnimplementedError(); | ||
} | ||
} | ||
|
||
class TestClient2 extends http.BaseClient { | ||
base class TestClient2 extends http.BaseClient { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto. Just no modifier. It's not a public class, so we don't care what people can do with it.
@@ -7,7 +7,7 @@ import 'dart:convert'; | |||
import 'dart:typed_data'; | |||
|
|||
/// A stream of chunks of bytes representing a single piece of data. | |||
class ByteStream extends StreamView<List<int>> { | |||
final class ByteStream extends StreamView<List<int>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(This class should not need to exist. It should just be extension methods on Stream<List<int>>
.)
EDIT I wrote a lot of wrong this below. TL;DR I made
interface Sendable {
Future<SendResponse> send(SendRequest request);
}
mixin BaseClient on Sendable {
...
} But I think that should be a separate change. Please correct me if I'm wrong - I've never actually used a mixin! |
Fixes #918