×

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

Common Collection Methods

Most of the programming languages have arrays as a way to list items together. However, Dart has a collection of data structures similar to array. These are supported by the...

3 minutes read.

Dart Function

A Dart function is a collective line of code that are targeted to perform a specialised task. Such lines of code (function) can be reused whenever we need to perform...

6 minutes read.

Dart Features

Dart is a fully-featured, object-oriented modern language with its roots in the programming language ‘Smalltalk’. It has some of its eminent features similar to the languages such as Java, C#...

4 minutes read.

Dart Concurrency

Dart concurrency allows us to run multiple or multiple components of a system at once. It issues several commands at once. Dart provides Isolates as a tool for performing compliance...

2 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.

Lexical Scope and Closure

Lexical Scope : Lexical scope is a very important term in any programming language. It defines the scope of the variable based on the block it is contained inside. According to...

2 minutes read.

Dart Inheritance

Inheritance is a promising concept of any programming language. It is a property by which a class inherits the property of another class. Moreover, the class deriving the properties of...

5 minutes read.

Dart this Keyword

The ' this ' keyword, similar to that in Java and C#, refers to an object of the class using it. It points to the current object of the class,...

5 minutes read.

Unit Testing in Dart

Typing testing ensures that your app keeps working as you add more features or change existing functionality. Unit testing helps to confirm the behavior of a single function, method, or...

4 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 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 Assignment Operator

Assignment operators are the operators that assign value to the variables. The value on the right-hand side is assigned to the variable on the left-hand side. We can also use...

4 minutes read.

Dart Bitwise and Shift Operators

The Bitwise operators are the operators that perform different operations bit by bit on the value of the two operands. List of Bitwise Operators in Dart Sr. Operators Description 1. & ( Binary AND ) It returns...

2 minutes read.

Dart Type Test Operators

Type Test Operators in Dart These operators are used to check the types of expressions at runtime. Dart is a typed language, and we often want to assert that a value...

1 minute 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 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 Anonymous Function

Dart functions are the user defined functions that are designed to perform specific task. The use case of the functions is that they can be directly called any number of...

3 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.

Dart If statement

If statement is used to set the control on the lines of code. Using if statement, block of code is executed only if the expression in the statement returns true....

1 minute read.

Dart Exception Handling

Exception Class – An exception is any runtime error that leads to abrupt termination of the program. It helps in addressing the error programmatically. It is aimed to be caught...

4 minutes read.