
- 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 - Methods
- Scala - Functions
- Scala - Methods vs 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 - Polymorphic Functions
- 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 - NumericRange
- Scala - Infinite Streams
- Scala - Parallel Collections
- Scala Advanced Types
- Scala - Union Types
- Scala - Intersection Types
- Scala - Type Aliases
- Scala - Structural Types
- Scala - Match Expression
- Scala - Singleton Type Operator
- Scala - Abstract Types
- Scala - Dependent Types
- Scala - Abstract Type Bounds
- Scala - Higher-Kinded Types
- Scala - Opaque Type Alias
- Scala - Path-Dependent Types
- Scala - Type Lambdas
- Scala - Type Inference
- Scala - Algebraic Data Types
- Scala Pattern Matching
- Scala - Pattern Matching
- Scala - Guards
- Scala - Variables in Patterns
- Scala - Type Patterns
- Scala - The Matchable Trait
- Scala - Matching Arrays
- Scala - Matching Lists
- Scala - Matching Tuples
- Scala - Exception Handling
- Scala - Extractors
- Scala - Pattern Bindings
- Scala - Regular Expressions
- Scala - Case Classes
- Scala - Partial Functions
- Scala - Packaging and Imports
- Scala - Implicit Imports
- Scala - Export Clauses
- Scala - Nested Packages
- Scala - Chained Packages
- Scala - Package Objects
- Scala Files I/O
- Scala - Files I/O
- Scala - Writing Files
- Scala - Listing Files
- Scala - Deleting Directories
- Scala - Check File Exists
- 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 - Process Management
- Scala - Scaladoc
- Scala - Literal Type Arithmetic
- Scala - Inline keyword
- Scala - Def, Var & Val
- Scala - Dropped Features
- Scala Unit Testing
- Scala - Unit Testing
- Scala - uTest
- Scala - MUnit
- Scala - ScalaTest Runner
- Scala - ScalaMock
- Scala - JUnit
- Scala - Mocking
- Scala - BDD Testing
Scala - Package Objects
You use packages to create namespaces in Scala. It prevents naming conflicts. Package objects are used to define functions, variables, and types that are accessible to all members of a package. You can share common definitions across the entire package. So, it improves code organization and maintainability.
What is a Package Object?
Package object is a singleton object named package. It is used to share methods, variables and type aliases across the entire package. Package objects are convenient containers for code and data. You can access these containers across multiple classes within the same package.
Creating a Package Object
You can create a package object in Scala easily. You can define object named package within a file named package.scala. For example -
// package.scala package com.example package object utils { def exampleMethod(): Unit = { println("This is an example method in the package object.") } }
In the code snippet above, we have created a package object named utils under the package com.example. The package object contains a method named exampleMethod().
Using a Package Object
Once a package object is defined, you can access its members directly from any other class in the same package. Following is the example which shows you how to use the exampleMethod() from another class -
// ExampleClass.scala package com.example.utils class ExampleClass { def printMessage(): Unit = { exampleMethod() } }
In this example, the ExampleClass can directly use exampleMethod() defined in the package object utils.
Example with Case Classes and Objects
Create a class, Person. It includes various attributes like, name, age, and designation. Now, the name of the project is company. So, the package and package object for its class would be as follows -
// in file company/person/Person.scala package company.person case class Person(name: String, age: Int, desig: String) object Male extends Person("Ahmad", 27, "Technical lead") object Female extends Person("Nida", 24, "Intern") // in file company/person/package.scala package company package object person { val employees = List(Male, Female) def showEmployee(person: Person): Unit = { println(s"Name: ${person.name}, Age: ${person.age}, Designation: ${person.desig}") } }
In the code above, the package object person is named after the case class Person. The package object includes a method definition showEmployee(). It prints the details of the employees.
Using Package Objects Across Files
Following is the example which shows you how to use the showEmployee() method from another class within the same package -
// in file company/person/Main.scala package company.person object Main { def main(args: Array[String]): Unit = { employees.foreach(showEmployee) } }
In this example, the Main object directly uses the employees list. The showEmployee method is defined in the package object person.
Usage of Package Objects
You can use Package objects in Scala to hold various definitions, including type aliases, implicit conversions, and utility methods. These support mixed inheritance. So, a single package object can extend more than one class (or trait).
Type Aliases and Implicit Conversions
Following is the example which shows you how to use type aliases and implicit conversions within a package object -
// in file foo/bar/package.scala package foo package object bar { type StringMap[+T] = Map[String, T] implicit def strToInt(s: String): Int = s.toInt }
In this example, the package object bar defines a type alias StringMap. Implicit conversion from String to Int.
Mixing Traits
You can extend Package objects to traits to include more functionality. For example -
// in file foo/bar/package.scala package foo trait Versioning { val version: String } trait Utility { def printVersion(): Unit = println(s"Version: $version") } package object bar extends Versioning with Utility { override val version: String = "1.0" }
In this example, the package object bar extends two traits, Versioning and Utility. These provide more methods and properties.
Package Objects for Namespace Management
Package objects are used for managing namespaces and utilities available throughout a package. For example, the library dealing with mathematical operations can define a package object with common constants and helper methods -
// in file math/package.scala package math package object constants { val Pi = 3.14159 val E = 2.71828 def sqrt(x: Double): Double = math.sqrt(x) }
In this example, the constants package object in the math package defines Pi, E, and a sqrt method. These are then used in the Operations object.
Restrictions
There are some restrictions of package objects. These are -
- Single Package Object - Only one package object is allowed per package.
- No Overloaded Methods - Overloading methods in package objects is not supported.
- File Naming - The source file for a package object should be named package.scala and placed in the corresponding directory of the package.
Package Objects Summary
- Package objects are used to define methods, variables, and type aliases that are accessible to all members of the package.
- Each package can have only one package object, which should be named package.scala and placed in the corresponding directory.
- Package objects support mixed inheritance. So, you can extend these classes and traits.
- You can use package objects for managing namespaces. These are also used in utilities that are accessible throughout the package.
- There is no support of overloading methods in package objects. Members cannot share names with top-level classes (or objects) in the same package.