×

Soundness in Dart

What is soundness?

Soundness ensures that the program never comes across any invalid state that may lead to abrupt termination of the program. As its name suggests it ensures perfect type matching that is the program can never get into the state where an expression evaluated to a value that doesn't match the static type of the expression.

For example if the static type of expression is String, we can only get a string value when we evaluate it at the runtime. Like in any other programming languages such as Java and C#, the Dart type system is also sound. It ensures the soundness using both static checking and runtime checking.

For example, if we asign a String to int is a compile - time error. Casting an object to a String using as String fails with a runtime error if the object isn’t a String.

Advantages of Soundness

There are various benefits of using sound type system: 

  • Revealing type-related bugs at compile time: A sound type system forces code to be unambiguous about its types, so type-related bugs that might be tricky to find at runtime are revealed at compile time.
  • More readable code: Code is easier to read because you can rely on a value actually having the specified type. In sound Dart, types can’t lie.
  • More maintainable code: With a sound type system, when you change one piece of code, the type system can warn you about the other pieces of code that just broke.
  • Better ahead of time (AOT) compilation: While AOT compilation is possible without types, the generated code is much less efficient.

Let's look at these rules in more detail, with examples using the following types of positions :

Animal sequence where the largest species is Animal and the subspecies are Snake, Cat, and Monkey. The cat has less breeds of Lion and Tiger

Use sound return types when overriding methods

The return type of a method in the subclass should be the same type or sub-type return method in the superclass. Consider how to find animals in the animal category :

class Animal {
  void chase( Animal a ) {  . . .  }
  Animal get parent => . . .
}

The parent getter( ) method returns ‘ Animal ’. In the ‘ Monkey ’ subclass, you can change the Getter recovery type with Monkey ( or any other sub-type of Animal ), but unrelated type is not allowed.

class Monkey extends Animal {
  @override
  void chase( Animal a ) { . . .  }
  @override
  Monkey get parent => . . .
}
class Monkey extends Animal {
  @override
  void chase( Animal a ) { . . . }
  @override
  Root get parent => . . .
}

Use sound parameter types when overriding methods

The output path parameter must have the same type or maximum corresponding parameter type in the superclass. " Do not override " the parameter type by substituting for the minimum version of the original parameter.

Note :

If you have good reason to use a subtype, you can use a covariant keyword.

Consider the ( Animal ) chase method of the Animal category:

class Animal {
  void chase( Animal a ) { . . . }
  Animal get parent => . . .
}

The chase( ) method takes an Animal. A ‘ Monkey ’ chases anything. It is okay to write down the chase( ) method of taking anything ( Object ).

class Monkey extends Animal {
  @override
  void chase( Object a ) { . . . }
  @override
  Animal get parent => . . .
}

The following code tightens the parameter on the chase( ) path from Animal to Mouse, a subclass ‘ Animal ’.

class Mouse extends Animal { . . . }
class Cat extends Animal {
  @override
  void chase( Mouse x ) { . . . }
}

This code is not a safe type because you will be able to identify the cat and send it after the Snake :

Animal a = Cat( ) ;
a.chase( Snake( ) ) ; // Not type safe or feline safe.

Do not use the dynamic list as a typed list.

A dynamic list is great if you want to have a list of different things in it. However, you cannot use dynamic lists as a typed list.

This rule also applies in cases of the general species.

The following code creates a dynamic list of Dogs, and gives it a list of Cat types, which creates an error during static analysis.

class Cat extends Animal { . . . }
class Dog extends Animal { . . . }
void main( ) {
  List< Cat > foo = < dynamic >[ Dog( ) ] ; // Error
  List< dynamic > bar = < dynamic >[ Dog( ), Cat( ) ] ; // OK
}

Runtime checks

Runtime checks in the Dart VM and dartdevc is dealing with security issues which the analyzer cannot handle.

For example, the following code does something different during operation because it is a mistake to publish a list of dogs in the cat list :

void main( ) {
List < Animals > animals = [ Dog ( ) ] ;
List < Cat > cats = animals as List < Cat > ;
}

Related Topics

Dart Operators Precedence and Associativity

Precedence of operators determines the order in which the operators are evaluated if they are grouped together in a sentence. If two operators share an operand then the one with...

5 minutes read.

Dart Packages

Every programming language has some in-built functions stored inside the header files that makes the task much easier for the programmer. The Dart Packages refer to the compilation of a...

4 minutes read.

Dart Constants

Dart Constants are the objects or variables whose values can’t change or modify during the execution of the program. Their use case is when we want a particular value to...

2 minutes read.

Dart Break and Continue

Loop statements are used to change the normal sequence of flow of the program. Dart supports two types of loop control statements: Break StatementContinue Statement Break Statement : The ‘ break ’ statement is...

4 minutes read.

Dart Optional Parameters

Dart functions can have optional parameters with default values. When we create a function, we can specify parameters that calling code can provide; but if the calling code chooses not...

2 minutes read.

Metadata in Dart

Metadata is often referred to as the data about the data. It is a  piece of data about a basic piece of data. In the case of a Dart program,...

2 minutes read.

Dart - Control Flow Statements

The control flow statements are used to define the control on the flow of the program. Dart programs are executed in sequential order i.e., the order in which the programming...

1 minute read.

Dart Object-Oriented Concepts

Dart is a programming language that supports object-oriented programming. It is focused on the objects that are real-world entities and supports all the concepts of OOPS, such as objects, classes,...

4 minutes read.

Dart Method Overriding

Before understanding method overriding, it is important to clear the concept of polymorphism. Polymorphism is derived from two Greek words 'Poly' which means many and 'morphs' which means many forms....

5 minutes read.

Dart Installation Guide

There are various ways of compiling and running an application created in Dart, either by compiling the Dart code to JavaScript using the Dart2js tool or by running on the...

3 minutes read.

Dart Queues

A queue is a user-defined collection of data. It is based on the FIFO principle ( First In First Out ) which implies that the element to be inserted first,...

3 minutes read.

Dart Static Members

Static Members in Dart Static members are the members of the class declared using the 'static' keyword. the static members have the following characteristics :  All the objects of the class having...

3 minutes read.

Dart lists data type

The most important data type in any programming language is an ordered list of elements, an array. Dart lists resemble JavaScript array lists. Example,               var...

7 minutes read.

main function in Dart

The main( ) function is a predefined method in Dart that is also known as the entry-point of the program. The compiler begins the execution only when it comes across...

3 minutes read.

Dart Equality and Relational Operators

Dart provides the functionality of checking the relationship between the values or values within the variables. These operators return the resultant value as Boolean, i.e., either ‘true’ or ‘false’. Some important points...

3 minutes read.

Dart Isolates

Dart successfully supports asynchronous programming which runs our program without any hindrance. This asynchronous programming is used to achieve concurrency. Dart supports concurrent programming with features such as ‘ async-await...

9 minutes read.

Dart Generators

Synchronous Generator Dart Generator is a unique function that allows us to generate price sequences. Generators return values when needed; means that the value is generated if we try to duplicate...

5 minutes read.

Dart If-else-if statement

If - else - if statement enables to check the set of test expressions that evaluate to Boolean True or False, and based on this true or false the particular...

2 minutes read.

Dart - extends, with and implements Keywords

The application development in Dart programming language using the Flutter framework, regularly experience different usage of the implements, extends and with keywords. Dart has full support for inheritance that is...

5 minutes read.

Dart Standard Input & Output

Standard Input in Dart (stdin): The standard input stream reads data both synchronously and asynchronously from the keyboard.  In Dart programming language, .readLineSync( ) function is used to accept input from the...

3 minutes read.