diff --git a/parameters/.gitignore b/parameters/.gitignore new file mode 100644 index 0000000..c2debcf --- /dev/null +++ b/parameters/.gitignore @@ -0,0 +1,8 @@ +# Files and directories created by pub. +.dart_tool/ +.packages + +# Conventional directory for build output. +build/ + +pubspec.lock diff --git a/parameters/README.md b/parameters/README.md new file mode 100644 index 0000000..caf4814 --- /dev/null +++ b/parameters/README.md @@ -0,0 +1,15 @@ +# Function parameters and super-initializer samples + +This sample demonstrates Dart's function parameters capabilities, +including named parameters, optional parameters, and the ability to have named +arguments anywhere in the argument list. + +As well, the sample demonstrates super-initializer parameters. + +These features are part of Dart 2.17. The programs in this folder won't +compile in earlier versions. + +## Instructions + +Read the source code in the `lib/` directory. The code is split into +separate files according to topics or use cases. diff --git a/parameters/analysis_options.yaml b/parameters/analysis_options.yaml new file mode 100644 index 0000000..572dd23 --- /dev/null +++ b/parameters/analysis_options.yaml @@ -0,0 +1 @@ +include: package:lints/recommended.yaml diff --git a/parameters/lib/named_parameters.dart b/parameters/lib/named_parameters.dart new file mode 100644 index 0000000..07228fe --- /dev/null +++ b/parameters/lib/named_parameters.dart @@ -0,0 +1,22 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// This example shows the use of named arguments and parameters. +/// +/// See the test under `../test/named_parameters_test.dart` for its use. + +/// Function that counts the amount of [items] that match a given [predicate], +/// with the option to skip the first [skip] elements. +/// +/// This function has three parameters: +/// - Required positional parameter [predicate] +/// - Required named parameter [items] +/// - Optional named parameter [skip] +int countWhere( + bool Function(T) predicate, { + required Iterable items, + int skip = 0, +}) { + return items.skip(skip).where(predicate).length; +} diff --git a/parameters/lib/super_initalizer.dart b/parameters/lib/super_initalizer.dart new file mode 100644 index 0000000..aee9311 --- /dev/null +++ b/parameters/lib/super_initalizer.dart @@ -0,0 +1,97 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// This example shows the use of super-initializer parameters. +/// +/// Super-initializer parameters allow to forward constructor parameters +/// to the superclass, avoiding having to write the parameter multiple times +/// in the superclass constructor invocation. + +/// This example contains multiple classes representing different types of +/// synthesizers, a musical instrument similar to a piano +/// which can be used to create new sounds. +/// +/// All subclasses inherit from the [Synth] class and take advantage of the +/// different super-initializer capabilities. +class Synth { + /// Model name + final String model; + + /// Amount of notes that can be played at the same time + final int polyphony; + + /// Amount of sound generators, default to 1 + final int oscillators; + + /// In the class constructor [model] is a positional parameter, + /// while [polyphony] and [oscillators] are named parameters. + Synth( + this.model, { + required this.polyphony, + this.oscillators = 1, + }); + + @override + String toString() { + return 'Synth $model. Polyphony: $polyphony, oscillators: $oscillators'; + } +} + +/// This class represents an old vintage synthesizer. +/// +/// [VintageSynth] can only have 1 oscillator. +/// [polyphony] is optional and is 1 by default. +class VintageSynth extends Synth { + /// [model] is forwarded to the super constructor. + /// Named parameter [polyphony] is forwarded, with the default value of 1. + VintageSynth(super.model, {super.polyphony = 1}); +} + +/// This class represents a modern digital synthesizer. +/// +/// [DigitalSynth] can only have 1 oscillator. +/// Named parameter [polyphony] is required. +class DigitalSynth extends Synth { + /// [model] is forwarded to the super constructor. + /// Named parameter [polyphony] is forwarded and it is required. + DigitalSynth(super.model, {required super.polyphony}); + + /// The following constructor declaration would not be possible + /// because [polyphony] is not a positional argument. + /// + /// DigitalSynth(super.model, super.polyphony); +} + +/// This class represents a complex multi-oscillator synthesizer. +/// +/// [MultiOscillator] requires all three parameters. +class MultiOscillatorSynth extends Synth { + /// This constructor has three positional parameters instead of one. + /// + /// [model] is forwarded to the super constructor. + /// [polyphony] and [oscillators] positional parameters are then passed to the + /// named parameters in the super constructor. + MultiOscillatorSynth( + super.model, + int polyphony, + int oscillators, + ) : super( + polyphony: polyphony, + oscillators: oscillators, + ); +} + +/// This class represents a synth with a fixed amount +/// of polyphony and oscillators. +/// +/// [FixedOscillatorSynth] only requires the positional parameter [model]. +class FixedOscillatorSynth extends Synth { + /// [model] is forwarded to the super constructor. + /// [polyphony] and [oscillators] are hardcoded. + FixedOscillatorSynth(super.model) + : super( + polyphony: 1, + oscillators: 3, + ); +} diff --git a/parameters/pubspec.yaml b/parameters/pubspec.yaml new file mode 100644 index 0000000..3e0f8d2 --- /dev/null +++ b/parameters/pubspec.yaml @@ -0,0 +1,12 @@ +name: parameters +description: Function parameters and super initalizers examples +version: 1.0.0 + +publish_to: none + +environment: + sdk: '>=2.17.0-182.1.beta <3.0.0' + +dev_dependencies: + lints: ^1.0.0 + test: ^1.16.0 diff --git a/parameters/test/named_parameters_test.dart b/parameters/test/named_parameters_test.dart new file mode 100644 index 0000000..1716ce1 --- /dev/null +++ b/parameters/test/named_parameters_test.dart @@ -0,0 +1,55 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:parameters/named_parameters.dart'; +import 'package:test/test.dart'; + +/// This example shows the use of named arguments. +/// +/// Starting in Dart 2.17, named arguments can be used at any position in the +/// arguments list, instead of only after the positional arguments. +/// +/// In the following tests, the method [countWhere] is called +/// with a different argument list order to show this. +void main() { + test('named argument after positional argument', () { + final list = [0, 2, 42, 91]; + + // `items` named argument appears after the positional argument `predicate` + // Default argument `skip` is not provided + final total = countWhere((item) { + return item % 2 == 0; + }, items: list); + + expect(total, 3); + }); + + test('named argument before positional argument', () { + final list = [0, 2, 42, 91]; + + // `items` named argument appears before the positional argument `predicate` + // Default argument `skip` is not provided + final total = countWhere(items: list, (item) { + return item % 2 == 0; + }); + + expect(total, 3); + }); + + test('positional argument between named arguments', () { + final list = [0, 2, 42, 91]; + + // positional argument `predicate` appears between + // named arguments `items` and `skip` + final total = countWhere( + items: list, + (item) { + return item % 2 == 0; + }, + skip: 1, + ); + + expect(total, 2); + }); +} diff --git a/parameters/test/super_initializer_test.dart b/parameters/test/super_initializer_test.dart new file mode 100644 index 0000000..58a670a --- /dev/null +++ b/parameters/test/super_initializer_test.dart @@ -0,0 +1,30 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:parameters/super_initalizer.dart'; +import 'package:test/test.dart'; + +void main() { + test('Create multiple instances of class Synth', () { + // Constructor with optional argument, provided + final juno = VintageSynth("Juno", polyphony: 6); + expect(juno.toString(), "Synth Juno. Polyphony: 6, oscilators: 1"); + + // Constructor with optional argument, not provided + final tb303 = VintageSynth("TB-303"); + expect(tb303.toString(), "Synth TB-303. Polyphony: 1, oscilators: 1"); + + // Constructor with required argument + final dx7 = DigitalSynth("DX7", polyphony: 6); + expect(dx7.toString(), "Synth DX7. Polyphony: 6, oscilators: 1"); + + // Constructor with required positional arguments + final ob6 = MultiOscillatorSynth("OB6", 5, 3); + expect(ob6.toString(), "Synth OB6. Polyphony: 5, oscilators: 3"); + + // Constructor with a single required positional arguments + final minimoog = FixedOscillatorSynth("MiniMoog"); + expect(minimoog.toString(), "Synth MiniMoog. Polyphony: 1, oscilators: 3"); + }); +}