avoid-classes-with-only-static-members
Same as avoid_classes_with_only_static_members in Dart lints
- Group
- Complexity
- Path
lint/complexity/avoid-classes-with-only-static-members- Default
- Off, opt in
- Origin
- Dart lints
- Rule
- 30 of 512
Flags a class that declares only static members.
Dart is not Java: free-standing functions and top-level variables do not need a class around them. A class whose every member is static — and which therefore is never instantiated for behavior of its own — only adds a namespace that a library (optionally imported with a prefix) already provides. Move the members to the top level instead.
class DateUtils { // flagged
static DateTime mostRecent(List<DateTime> dates) => dates.last;
}
DateTime mostRecent(List<DateTime> dates) => dates.last; // preferred
A class holding only static const fields (a group of constants) is
allowed, as are sealed classes and classes with a non-default constructor.
Like the analyzer, a class is skipped when its merged interface contains an
instance member owned by a class other than Object; members replaced by
mixin declarations do not count. Without resolution, only local mixins are
considered member-free supertypes.
Invalid
// Only static methods: move them to the top level.
class DateUtils {
static DateTime mostRecent(List<DateTime> dates) =>
dates.reduce((a, b) => a.isAfter(b) ? a : b);
}
// Static non-const fields count as instance-free state.
class _Favorites {
static int mostFavorite = 0;
}
// A static getter induces a non-const field.
class Config {
static String get name => 'config';
}
// A default constructor does not make the class a real type.
class Helpers {
Helpers();
static void run() {}
static const int retries = 3;
}
// `extends Object` adds no members.
abstract class Registry extends Object {
static final List<String> names = [];
static void register(String name) => names.add(name);
}
// Static setter plus static method.
class Counter {
static int _count = 0;
static set count(int value) => _count = value;
static void reset() => _count = 0;
}
// Unlike members inherited from a class, mixin members do not exempt this lint.
mixin Greets {
void greet() {}
}
class Greeter with Greets {
static void helper() {}
}
// Empty and static-only parents do not contribute instance members.
class EmptyParent {}
class ExtendsEmpty extends EmptyParent {
static int value = 1;
}
class ImplementsEmpty implements EmptyParent {
static int value = 1;
}
class StaticParent {
static int value = 1;
}
class ExtendsStatic extends StaticParent {
static void helper() {}
}
mixin class StaticMixinClass {
static int value = 1;
}
// Only the merged interface's owners count, not overridden class declarations.
class MethodParent {
void run() {}
}
mixin ReplacesMethod on MethodParent {
void run() {}
}
class ReplacedMethod extends MethodParent with ReplacesMethod {
static void helper() {}
}
class AccessorParent {
int get value => 0;
set value(int value) {}
}
mixin ReplacesAccessors {
int get value => 1;
set value(int value) {}
}
class ReplacedAccessors extends AccessorParent with ReplacesAccessors {
static void helper() {}
}// Only static methods: move them to the top level.class DateUtils {// Static non-const fields count as instance-free state.class _Favorites {// A static getter induces a non-const field.class Config {// A default constructor does not make the class a real type.class Helpers {// `extends Object` adds no members.abstract class Registry extends Object {// Static setter plus static method.class Counter {}class Greeter with Greets { class ExtendsEmpty extends EmptyParent { class ImplementsEmpty implements EmptyParent { class StaticParent { class ExtendsStatic extends StaticParent { mixin class StaticMixinClass {}class ReplacedMethod extends MethodParent with ReplacesMethod {}class ReplacedAccessors extends AccessorParent with ReplacesAccessors {Valid
// A group of constants is allowed.
class Color {
static const red = '#f00';
static const green = '#0f0';
static const blue = '#00f';
}
// Instance members make it a real class.
class Point {
final int x;
Point(this.x);
static Point origin() => Point(0);
}
// Sealed classes are exempt.
sealed class Shape {
static Shape? parse(String text) => null;
}
// A named constructor is not a default constructor.
class Logger {
Logger.named();
static void log(String message) {}
}
// A supertype other than Object may contribute instance members.
class Base {
void run() {}
}
class Derived extends Base {
static void helper() {}
}
class Impl implements Base {
@override
void run() {}
static void helper() {}
}
// An empty class has no members at all.
class Marker {}
// Top-level functions instead of a static-only class.
DateTime mostRecent(List<DateTime> dates) => dates.first;
// A mixin class's instance members also provide a real interface.
mixin class InstanceMixinClass {
void run() {}
}
class InheritsMixinClass extends InstanceMixinClass {
static void helper() {}
}
// One surviving class-owned member still exempts the class.
class TwoMethods {
void first() {}
void second() {}
}
mixin ReplacesFirst {
void first() {}
}
class PartiallyReplaced extends TwoMethods with ReplacesFirst {
static void helper() {}
}
// Getter and setter ownership must remain separate.
class AccessorParent {
int get value => 0;
set value(int value) {}
}
mixin ReplacesGetter {
int get value => 1;
}
class RetainsSetter extends AccessorParent with ReplacesGetter {
static void helper() {}
}Configure avoid-classes-with-only-static-members
Set its severity in falcon.json. See the configuration guide.
{
"linter": {
"rules": {
"complexity": {
"avoid-classes-with-only-static-members": "error"
}
}
}
}Or silence one occurrence with a suppression comment; the reason is required.
// falcon-ignore lint/complexity/avoid-classes-with-only-static-members: <reason>More complexity rules
- avoid-collapsible-if
Flags an else-free
ifwhose only then-statement is another else-freeif. - avoid-complex-arithmetic-expressions
Reports arithmetic expressions containing too many terms.
- avoid-complex-conditions
Flags boolean expressions with more logical operands than the configured threshold.
- avoid-complex-loop-conditions
Flags loop conditions with more logical operands than the configured threshold.
- avoid-function-literals-in-foreach-calls
avoid_function_literals_in_foreach_callsFlags a function literal passed to an Iterable's
forEach. - avoid-if-with-many-branches
Reports long if/else-if chains; replace them with a switch or extracted helpers.
- avoid-inverted-boolean-expressions
avoid_inverted_boolean_expressionsrecommendedFlags a doubly-negated boolean expression such as
!!x. - avoid-long-records
Reports record values and record types with too many fields.