PK - Chapter 3 Flashcards Preview

Kotlin 101 > PK - Chapter 3 > Flashcards

Flashcards in PK - Chapter 3 Deck (50):

Declare a class named Foo.

class Foo {



What is the default access level of a class ?



Explain class constructors.

  • as in Java, an empty constructor is generated by default
  • a primary constructor can be specified in the class declaration
  • parameters in the primary constructor are properties
    of the instance
  • secondary constructors can be created in the body of
    the class using the constructor keyword
  • constructors can reference other constructors
  • secondary constructors must directly/indirectly invoke the
    primary constructor; primary must always be invoked


Create a primary constructor for class Foo, with data validation.

class Foo (firstArg: String?, secondArg: Int?) {
    init {
        require(! firstArg.isNullOrEmpty()) { "First argument cannot be null or empty." }
        require(! secondArgument.isNull()) { "Second argument cannot be null or empty."  }

require will throw an IllegalArgumentException with the
message provided, if the condition is false.


Explain initializer blocks.

  • syntax is
    init {
  • initializer blocks are executed in the same order as they appear in the class body
  • initializer blocks can be interleaved with the property initializers
  • parameters of the primary constructor can be used in initializer blocks


Explain primary constructors.

  • a primary constructor is specified in the class declaration
  • any code run as part of the primary constructor needs to be in an init block
  • parameters in the primary constructor are properties of the instance,
    if they include the "val" or "var" keyword
  • primary constructor does not require the constructor keyword, if it
    does not have any annotations or visibility modifiers

class Foo private constructor(firstArg: Int, secondArg: String) {
    init {  ifNeeded(firstArg }


Explain secondary constructors.

  • secondary constructors can be created in the body of a class using the constructor keyword
  • constructors can reference other constructors
  • secondary constructors must directly or indirectly call the primary constructor


Given the class

class Person constructor(val firstName: String, val lastName: String) {}

val fooPerson = Person("John", "Doe")

Print the person's first and last name for instance fooPerson.

println("${fooPerson.getFirstName} ${fooPerson.getLastName}")


Note that the getters (and setters for a var) will not be generated for
primary constructor parameters if val and var are not specified.  This
will make them private to the class.


What is the recommended visibility
for the constructors or an abstract class ?



They would only be visible to derived classes.


Define a primary constructor for class Foo
that can only be instantiated inside the package.

class Foo internal constructor(firstArg: String, secondArg: Int) {



Note that there are no "val" or "var" keywords, so the
constructor parameters are not properties of the object.


Summarize visibility levels.

4 visibility levels:

  • public
    Visible to everyone everywhere
  • private
    Only visible in the file defining it
  • protected
    Only visible to subclasses, extensions 
    and implementers
  • internal
    Visible from anywhere within the module


What is the access to a private nested class ?

Can create/access an instance from the outer class.


What is the access to an internal nested class ?

Can be created/accessed from anywhere in the module.


What is the access to an protected nested class ?

Can be created/accessed from any class
that is derived from the containing class.


What is the difference between static and non-static nested classes ?

Static nested class:

  • can only access the public members
    of the enclosing class
  • not defined with the inner keyword

Inner class (non-static class):

  • has access to the enclosing class members,
    even if declared private
  • can only be created from an instance of an
    enclosing class
  • defined with the inner keyword


How would you access the "memberOne" variable
in outer class "Alpha"
from inner class "Bravo" ?



Since we are referencing it from an inner class,
the visibility of memberOne does not matter.


How would you access the "memberOne" variable
in outer class "Alpha"
from nested static class "Bravo" ?



The nested static class can only access the
member variable if it is public.


Add a MouseListener to a button,
using an anonymous inner class.

button.addMouseListener(adapter : MouseAdapter() {
    override fun mouseClicked(event: MouseEvent) { this@OuterClass.doSomething() }


Define a data class named "Person"
with attributes "firstName", "lastName".

data class Person(val firstName: String, val lastName: String)


Define an enum named "DayOfWeek"
with attribute "properCaseName".

enum class DayOfWeek(val properCaseName: String) {


What are the built-in properties of an enum instance ?

name: String
ordinal: Int


Create an interface named "Printable" and
an enum named "Word" that implements Printable.

interface Printable {
    fun print(): Unit

enum class Word : Printable {
    HELLO {
        override fun print() {
            println("Word is Hello")
    BYE {
        override fun print() {
            println("Word is Bye")

val word = Word.HELLO


Create a class with static methods.

Kotlin doesn't directly support static methods for a class.

Methods accessed statically must be defined
in a companion object.


What is a companion object ?

"class" is used to define classes
that have multiple instances.


"companion object" is used to define a singleton
object instantiated at runtime.
It is a "class object" defined within a class body.


Create an anonymous companion object
inside class Foo.

class Foo {
    companion object {
        fun returnOne() : Int = 1


This can be referenced as:


Create a named companion object
inside class Foo.

class Foo {
    companion object Barr {
        fun returnOne() : Int = 1


This can be referenced as:


What are the characteristics of a companion object ?

  • is a singleton created at runtime for the class
  • has access to the private methods
    ​and properties of the containing class's objects
  • is only useful if it needs access to the private
    members of the containing class; else just
    declare "top level" properties and functions in the file
  • can implement interfaces and extend other classes
  • can be anonymous or named
  • can only have one anonymouse companion object


Define a static method that can be called from Java.

class Foo {
    companion object {
        @JvmStatic fun bar() {}


Create a singleton.

// factory pattern
class ServiceManager private constructor(val pName: String) {
    companion object {
        fun create(pNewName: String): ServiceManager {
            return ServiceManager(pNewName)

val myServiceManager = ServiceManager.create("SomeName")


How would you access method bar() in
Foo's companion object explicitly ?


What are the characteristics of an Interface ?

An interface can contain:

  • abstract methods
  • method implementations
  • properties, but not state (no assignments)


Implementing or overriding any of these in a class definition


What is the difference between an interface and an abstract class ?

  • an interface cannot contain state, a class can
  • a class can implement multiple interfaces,
    but only inherit from one abstract class


What are the characteristics of Any ?

  • Any is the base class for Kotlin
  • if a class does not extend a super class,
    it extends Any
  • Any implements a subset of methods
    found in the Java Object class
  • common methods:
        equals(arg list): Boolean
        hashCode(): Int
        toString(): String


When can you extend a class ?

A class cannot be extended unless
it is declared with the open keyword.


Given the following base class,
define a subclass named "CardPayment"
with the additional constructor parameters
of "description" and "accountNumber".


open class Payment(val payment: BigDecimal) { }

class CardPayment(
  val pDescription: String, cardNumber: String, val amount: BigDecimal):
  Payment(amount) { } 


What is a sealed class ?

A sealed class cannot be extended.

Classes are sealed by default.

The open keyword must be used when
defining a class that is not sealed.


Define a sealed class "Foo".

class Foo { }


Define a class "Foo" that can be extended.

open class Foo { }


Define class "Foo".
Extend class "Bar".
Implement (empty/marker) interfaces "Learn" and "More".

class Foo : Bar, Learn, More { }
class Foo : Learn, More, Bar { }
class Foo : Learn, Bar, More { }


Any ordering of superclass and interface(s) is fine.


Can the scope of a protected member
be expanded to public ?

Yes, if it is defined "open".
Redefining the field will NOT replace the existing one,
when it comes to object allocation.


open class Container {
    protected open val fieldA: String = "Some value"

class DerivedContainer : Container() {
    public override val fieldA: String = "Something else"


Describe an abstract class.

  • specified with the abstract keyword in the class definition
  • abstract methods must also include the abstract keyword
  • cannot create an instance of an abstract class
  • concrete extensions of the class must implement all abstract methods
  • abstract class can extend a concrete class, and override parent method
    as abstract, if the parent method is open.  Parent method will no longer
    be accessible


When should you create
an interface versus an abstract class ?

  • is-a versus can-do
  • versioning - if you add a method to an interface,
    all classes that implement that interface must be
    updated to implement the new interface
  • interfaces cannot initialize state
  • interfaces do not have a constructor or factory
  • subclasses can only extend one superclass/abstract


Explain late-binding polymorphism.

Also known as dynamic binding or runtime binding.

Base classes define and implement virtual methods.

Subclasses can override virtual methods that are open.

When a virtual method is called, the type of the
current receiver is determined at runtime and
the implementation of that type is executed.


I there a runtime performance penalty for
creating deep inheritance hierarchies ?



Virtual method calls are expensive,
because they have to search through
the entire class hierarchy at runtime to
determine which implementation to execute.


What are the overriding rules ?

  • both methods and properties (val) can be overridden
  • by default, methods and properties are closed and cannot be overridden
  • a method or property definition must include open to make it available
    to be overridden in a subclass
  • the override keyword must be used when overriding a
    method or property in a subclass
  • you can override a val with a var, but not the other way around
  • if a superclass and an interface implement the same method signature,
    the subclass must implement the method.  The method may call the others:


What are the 2 types of composition ?

  • aggregation - "assocated-with"
    The object lifecycle is independent from the
    container lifecycle.  Container can be destroyed,
    but the aggregated objects can live on.
  • composition - "part-of"
    The object lifecycle is tied to the container
    lifecycle.  If the container is destroyed, so are
    the composed objects.
    These objects are constructed by the container
    and are frequently private.


Why should you
favor composition over inheritance ?

  • deep class hierarchies are less efficient at runtime
  • single responsibility
  • simplicity of design
  • reduce type coupling
  • greater flexibility
  • easy to delegate to a different type


What is a sealed class ?

  • defined with the sealed keyword
  • abstract class
  • can be extended by subclassed
    nested in the sealed class
  • a powerful enumeration option that
    supports multiple instances of each
  • powerful when used in a collection
    with a when statement



Given the following inheritance,
how would you access a method implementation
foo()" in class "A" from class "C", if it
has been overridden in class "B" ?