01 logo

Scala Beginner Series (2) : Object Oriented Scala

This article will cover the object oriented nature of Scala language.

By Mansi BabbarPublished 3 years ago 7 min read
3

This series is all about the taste of Scala. It is best suitable for all the newbies in Scala.

You may also like: Scala Beginner Series (1) : Basics

In the previous part, we covered:

  • Values, variables, expressions and types
  • Functions and recursion
  • The Unit type

In this article we will cover the object oriented nature of Scala language.

Classes

Scala has the same concept of a class as we have in other languages.

Classes in Scala are blueprints for creating objects. They can contain methods, values, variables, objects, traits and super-classes which are collectively called members. Fields and methods are accessed with the dot operator similar to the other languages.

Also, all fields and methods of classes are public by default, unless we restrict their visibility with the private and protected modifiers. We don't have to specify public access modifier explicitly.

A minimal class definition is simply the keyword class and an identifier. The keyword new is used to create an instance of the class.

Constructors

Classes in Scala can take arguments — those are the constructor arguments. When we define a class, we can also define its constructor signature.

Beware that constructor arguments are not class fields . Parameters without val or var are private values, visible only within the class. Thus the following code will generate error:

Thus in order to promote constructor arguments to class fields, we can put a val or var before the argument name.

Inheritance

When a class inherits from another, it means it extends another. This lets a class inherit members from the one it extends and provides the code re-usability.

To carry out Scala inheritance, we use the keyword extends:

In the above example of two classes, Person class is base class or super-class and Employee class is derived class or sub-class.

extends clause has two effects:

  • It makes Employee class inherit all non-private members of Person class
  • It makes the type Employee a subtype of the type Person .

Scala also allows only single class inheritance just like Java.

Scala has the same subtype polymorphism that we have seen in other statically typed object oriented languages. In subtype polymorphism, instance of subclass can be passed to a base class.

At compile time, compiler only knows that we are calling demo() method of Element object. But at run time, the most derived method i.e. demo() method of ArrayElement is called. A derived class can, of course, override their super class methods.

Abstract Classes

Scala also has a concept of an abstract class that is similar to Java’s abstract class, which contains both abstract and non-abstract methods and cannot support multiple inheritances. They can’t be instantiated as well.

To implement Scala abstract class, we use the keyword abstract against its declaration:

It is also mandatory for a child to implement all abstract methods of the parent class. Abstract methods of abstract class are those methods which do not contain any implementation.

Traits

Traits in Scala are similar to Java’s Interfaces. Classes and objects can extend traits, but traits cannot be instantiated and therefore have no parameters.

Traits are like partially implemented interfaces. It may contain abstract and non-abstract methods. It is possible that all methods are abstract, but it should have at least one abstract method.

Classes which extend the traits have to implement the abstract methods of the trait, but need not to implement the concrete methods of the trait.

To define trait, we use the trait keyword:

Scala has single-class inheritance and multi-trait mixing. It is possible to extend any number of Scala traits with a class or with an abstract class.

Anonymous Classes

Scala also has the concept of anonymous classes much like Java.

We already saw how to implement parent class’s declared methods. A less formal way to provide the implementation for a parent class’s methods is with an anonymous class, a non-reusable and nameless class definition.

To define a one-time anonymous class, instantiate the parent (and potentially abstract) class and follow the class name and parameters with curly braces containing the implementation.

The result is an instance that does extend the given parent class with a one-time implementation, but can be used like an instance from a traditional class definition.

To the compiler, anonymous class looks like this:

With anonymous classes, the compiler does a lot of work behind the scenes. This allows us to abstract that complexity away from our code.

Singleton Objects

There is no idea of static in Scala, instead we have singleton objects.

An object is a class that has exactly one instance. It is created lazily when it is referenced, like a lazy val. The methods and fields declared inside singleton object are globally accessible, we don’t need an object to access them. We can import them from anywhere in the program. Also, we can’t pass parameters to its primary constructor.

A singleton object is declared using the object keyword:

A singleton object can extend classes and traits. It also provides an entry for program execution. Without such an object, the code compiles but produces no output.

Companion Objects

When a singleton object is named the same as a class, it is called a companion object, and the class is called companion class. The companion class-object pair has to be in a single source file. Either member of the pair can access its companion’s private members. We use a companion object for methods and values which are not specific to instances of the companion class.

I have entered :paste mode here because I am working in the REPL. Since companions need to be in same source file, so :paste mode in REPL allows companions to be defined together.

static members in Java are modeled as ordinary members of a companion object in Scala.

The Apply Method

Scala classes as well as Scala objects, both offer a default method that we name as the apply method. We sometimes call it an injector method. We can also invoke this method without a name. Let me show you what I mean:

Remember, apply is just a special function that lets us call the parent object directly, like a function. It has nothing to do with object orientation, classes, or constructors in the slightest.

We can use apply in companion objects as factory methods. The idea of the factory method is to construct class instances without new .

Case Classes

Scala case classes are like regular classes with a few key differences which we will go over. When the compiler sees the case keyword in front of a class, it generates code for us, with the following benefits:

  • Scala case classes are immutable by default and decomposable through pattern matching.
  • It does not use new keyword to instantiate object. This is because case classes have an apply method by default which takes care of object construction.
  • An unapply method is generated, which lets us to use case classes in more ways in match expressions.
  • A default toString method is generated, which is helpful for debugging.
  • equals and hashCode methods are generated, which let us compare objects and easily use them as keys in maps. It is used to check the value equality of all individual member fields instead of just checking the reference equality of the objects.
  • We can create a shallow copy of an instance of a case class simply by using the copy method. We can also change the constructor arguments.
  • All the parameters listed in the case class are public and val by default. It is possible to use var in case classes but this is discouraged.
  • Case objects

    A case object is like an object, but just like a case class has more features than a regular class, a case object has more features than a regular object. Its features include:

    • It’s serializable
    • It has a default hashCode implementation
    • It has an improved toString implementation

    The biggest advantage of case classes and case objects is that they support pattern matching. Pattern matching is a major feature of functional programming languages, and Scala’s case classes and objects provide a simple way to implement pattern matching in match expressions and other areas.

    You may also like: Pattern Match Anything in Scala

    Stay Tuned…

    Stay tuned for our next part of Scala Beginner Series where we will cover the functional nature of Scala. You don’t want to miss it!

    Originally published on Medium by Mansi Babbar.

    tech news
    3

    About the Creator

    Reader insights

    Be the first to share your insights about this piece.

    How does it work?

    Add your insights

    Comments

    There are no comments for this story

    Be the first to respond and start the conversation.

    Sign in to comment

      Find us on social media

      Miscellaneous links

      • Explore
      • Contact
      • Privacy Policy
      • Terms of Use
      • Support

      © 2024 Creatd, Inc. All Rights Reserved.