
- Scala - Home
- Scala - Overview
- Scala - Features
- Scala - Environment Setup
- Scala - Build Tool (SBT)
- Scala - REPL
- Scala - Dot & Dotty
- Scala - Basic Syntax
- Scala - Hello World Program
- Scala - Identifiers
- Scala - Keywords
- Scala - Comments
- Scala - Code Blocks
- Scala - Semicolon
- Scala - Constructs
- Scala - Expressions
- Scala - Input and Output
- Scala - Optional Braces
- Scala - Underscore (_)
- Data Types and Variables
- Scala - Data Types
- Scala - Type Bounds
- Scala - Context Bound
- Scala - Variances
- Scala - Type Hierarchy
- Scala - Variables
- Scala - Variable Scopes
- Scala - Literals
- Scala - Numeric Types
- Scala - Boolean Types
- Scala - Char Type
- Scala - Unit Types
- Scala - Strings
- Scala - Arrays
- Scala - Null Type
- Scala - Nothing
- Scala - Any Type
- Scala - AnyRef Type
- Scala - Unified Types
- Scala - Dates and Times
- Scala - Ranges
- Scala - Multidimensional Arrays
- Scala - WrappedArray
- Scala - StringBuilder
- Scala - String Interpolation
- Scala - StringContext
- Scala - Type Casting
- Scala var vs val
- Scala Operators
- Scala - Operators
- Scala - Rules for Operators
- Scala - Arithmetic Operators
- Scala - Relational Operators
- Scala - Logical Operators
- Scala - Bitwise Operators
- Scala - Assignment Operators
- Scala - Operators Precedence
- Scala - Symbolic Operators
- Scala - Range Operator
- Scala - String Concatenation Operator
- Scala Conditional Statements
- Scala - IF ELSE
- Scala - IF-ELSE-IF-ELSE Statement
- Scala - Nested IF-ELSE Statement
- Scala Loop Statements
- Scala - Loop Statements
- Scala - while Loop
- Scala - do-while Loop
- Scala - Nested Loops
- Scala - for Loop
- Scala - break Statement
- Scala - yield Keyword
- Scala Classes & Objects
- Scala - Classes & Objects
- Scala - Constructors
- Scala - Auxiliary Constructor
- Scala - Primary Constructor
- Scala - This Keyword
- Scala - Nested Classes
- Scala - Getters and Setters
- Scala - Object Private Fields
- Scala - Singleton Object
- Scala - Companion Objects
- Scala - Creating Executable Programs
- Scala - Stateful Object
- Scala - Enumerations
- Scala - Polymorphism
- Scala - Access Modifiers
- Scala - Apply Method
- Scala - Update Methods
- Scala - UnapplySeq Method
- Scala - Inheritance
- Scala - Extending a Class
- Scala - Method Overloading
- Scala - Method Overriding
- Scala - Generic Classes
- Scala - Generic Functions
- Scala - Superclass Construction
- Scala Methods & Functions
- Scala - Functions
- Scala - Main Methods
- Scala - Functions Call-by-Name
- Scala - Functions with Named Arguments
- Scala - Function with Variable Arguments
- Scala - Recursion Functions
- Scala - Default Parameter Values
- Scala - Functions without Parameters
- Scala - Implicit Parameters
- Scala - Higher-Order Functions
- Scala - Nested Functions
- Scala - Extension Methods
- Scala - Anonymous Functions
- Partially Applied Functions
- Scala - Lazy Val
- Scala - Pure Function
- Scala - Currying Functions
- Scala - Control Abstractions
- Scala - Corecursion
- Scala - Unfold
- Scala - Tail Recursion
- Scala - Infinite Sequences
- Scala - Dynamic Invocation
- Scala - Lambda Expressions
- Scala Collections
- Scala - Collections
- Mutable and Immutable Collections
- Scala - Lists
- Scala - Sets
- Scala - Maps
- Scala - TreeMap
- Scala - SortedMap
- Scala - Tuples
- Scala - Iterators
- Scala - Options
- Scala - Infinite Streams
- Scala - Parallel Collections
- Scala - Algebraic Data Types
- Scala Pattern Matching
- Scala - Pattern Matching
- Scala - Type Patterns
- Scala - Exception Handling
- Scala - Extractors
- Scala - Regular Expressions
- Scala Files I/O
- Scala - Files I/O
- Scala Advanced Concepts
- Scala - Closures
- Scala - Futures
- Scala - Promises
- Scala - Traits
- Scala - Trait Mixins
- Scala - Layered Traits
- Scala - Trait Linearization
- Scala - Sealed Traits
- Scala - Transparent Traits
- Scala - Literal Type Arithmetic
- Scala - Inline keyword
- Scala - Def, Var & Val
- Scala - Dropped Features
- Scala - BDD Testing
Scala - Type Bounds
Type Bound in Scala is like a rule. Type Bound limits what a parameter and variable can be. You can set the limits for the variables in the Scala. You can also put code into real world examples. In Scala, type bounds have the same purpose by imposing some restrictions on factors.
Types of Type Bounds
There are two types of type bounds. These are Upper type bound and lower type bound. We will discuss these both upper and lower type bounds here.
1. Lower Type Bound
Lower type bound is used to declare a higher type for another using lower type bounds. You can use >: for a lower bound in Scala. You can write a lower bound as `[T >: S]` in Scala, where S is a type and T is a type parameter. The statement says T must be S or a bigger type than S.
What is Supertype here ? Supertypes are higher types for another using lower type bounds. For example, S >:T this lower bound has T is less than or equal to S. It means T is bound in this case. Therefore, T is a supertype of S.
Syntax
[T >: Demo[T]]
We have a lower defined lower bound T which must be either Demor or Supertype of Demo type.
For example, if we declare all classes in a specific format, like this:
trait Animal class Mammal extends Animal class Bird extends Animal class Dog extends Mammal class Cat extends Mammal class Parrot extends Bird class Penguin extends Bird class Habitat[A](val location: A)
All classes and subclasses are now declared with the above statements. In the statement Habitat[A], 'Habitat' is general, and 'A' is the abstract type. You can put, Habitat[A] means the value for 'location' must be of type A. If you use the command Habitat[fruits], it creates an instance of the 'Fruits' type.
For example,
new Habitat[fruits](new fruits) new Habitat[fruits](new drinks) new Habitat[eatables](new vegetables)
In the given example, the first statement compiles. But the second shows errors because 'fruits' and 'drinks' are different types. However, the third statement compiles because 'vegetable' is a subtype of 'eatables.'
For example, using lower bound in the above statements:
class Habitat[A >: fruits](val location: A)
So, in this statement, you position any supertype of 'fruits' like 'eatables' or 'Habitat'. Therefore, you can see that Scala lower bounds are useful and adaptable in real-world examples with logical reasoning. You can impose real-life limitations on variables used in the coding language.
Example
// Scala Program To Demonstrate Scala Lower Bound class Tutorialspoint class Author extends Tutorialspoint class Tutorial extends Tutorialspoint class ComputerSciencePortal { // Declaration of Lower bound def display[T >: Tutorial](d: T) { println(d) } } // Object created object ScalaUpperBounds { // Driver code def main(args: Array[String]) { val tutorialspoint = new Tutorialspoint val author = new Author val tutorial = new Tutorial val computerscienceportal = new ComputerSciencePortal computerscienceportal.display(tutorialspoint) computerscienceportal.display(tutorial) computerscienceportal.display(author) } }
Output of this code will be:
Tutorialspoint@<hashCode> // Output of computerscienceportal.display(tutorialspoint) Tutorialspoint@<hashCode> // Output of computerscienceportal.display(tutorial) Author@<hashCode> // Output of computerscienceportal.display(author)
In the class 'computerscienceportal' a lower bound is set. 'tutorialspoint' is the superclass of 'Author,' and it's accepted in the lower bound.
Example
// Scala Program To Demonstrate Scala Lower Bound class Animal class Mammal extends Animal class Dog extends Mammal class Cat extends Mammal class Zoo { // Declaration of lower bound def display[T >: Mammal](m: T) { println(m) } } // Object created object ScalaUpperBounds { // Driver code def main(args: Array[String]) { // Defined new variable val animal = new Animal val mammal = new Mammal val dog = new Dog val cat = new Cat val zoo = new Zoo zoo.display(animal) zoo.display(mammal) zoo.display(dog) zoo.display(cat) } }
Output of above code will be,
Animal@<hashCode> // Output of zoo.display(animal) Mammal@<hashCode> // Output of zoo.display(mammal) Dog@<hashCode> // Output of zoo.display(dog) Cat@<hashCode> // Output of zoo.display(cat)
2. Upper Type Bound
Scala restricts Type Parameters and Type Variables with type bounds, and Upper bound is one of them. Implementing Type Bounds clarifies Type Variable constraints. It limits their specific values and details about their types of members. We use an upper bound on type parameters.
Syntax
[T <: S]
In '[T <: S],' 'T' is a type parameter, and 'S' is a type. It means T must be either S or a subtype of S.
For example, upper bound,
// Scala Program To Demonstrate Scala Upper Bound class Tutorialspoint class Author extends Tutorialspoint class Tutorial extends Author class OnlineLearningPortal { // Declaration of upper bound def display[T <: Author](d: T) { println(d) } } // Object created object ScalaUpperBounds { // Driver code def main(args: Array[String]) { val tutorialspoint = new Tutorialspoint val author = new Author val tutorial = new Tutorial val onlineLearningPortal = new OnlineLearningPortal // onlineLearningPortal.display(tutorialspoint) // This line is commented out because tutorialspoint does not satisfy the upper bound constraint. onlineLearningPortal.display(tutorial) onlineLearningPortal.display(author) } }
Output of this code will be,
Tutorial@<hashCode> // Output of onlineLearningPortal.display(tutorial) Author@<hashCode> // Output of onlineLearningPortal.display(author)
In the 'onlineLearningPortal' class, an upper bound is set. Since 'Tutorialspoint' is the superclass of 'Author', it is not accepted.
Example
// Scala Program To Demonstrate Scala Upper Bound class Employee class Manager extends Employee class TeamLead extends Manager class Company { // Declaration of upper bound def display[T <: Manager](t: T) { println(t) } } // Object created object ScalaUpperBounds { // Driver code def main(args: Array[String]) { // Defined new variable val employee = new Employee val manager = new Manager val teamLead = new TeamLead val company = new Company // company.display(employee) // This line is commented out because the employee does not satisfy the upper bound constraint. company.display(manager) company.display(teamLead) } }
Output of this code will be,
Manager@<hashCode> // Output of company.display(manager) TeamLead@<hashCode> // Output of company.display(teamLead)
In the 'Company' class, we have set an upper bound as [T <: Manager]. This means the 'display' method accepts objects of the 'Manager' class or its subclasses (like 'TeamLead'). Superclasses of 'Manager' will not be accepted. If the superclass of 'Manager,' i.e., 'Employee,' is not commented, a type mismatch error will occur.