0% found this document useful (0 votes)
267 views74 pages

Kotlin OOPs

The document discusses Kotlin object-oriented programming concepts including classes, objects, constructors, nested classes, inner classes, and more. Specifically: - Kotlin supports OOP through classes and objects which allow encapsulation, inheritance, and polymorphism. Classes define the blueprint for objects and contain properties and functions. - Objects are instances of classes that have state in their properties and behavior through functions. Multiple objects can be created from a class. - Constructors initialize an object's properties. Primary constructors are defined in the class header while secondary constructors use the constructor keyword. - Nested classes are declared within other classes while inner classes use the inner keyword and can access private members of outer classes

Uploaded by

subbareddy
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
267 views74 pages

Kotlin OOPs

The document discusses Kotlin object-oriented programming concepts including classes, objects, constructors, nested classes, inner classes, and more. Specifically: - Kotlin supports OOP through classes and objects which allow encapsulation, inheritance, and polymorphism. Classes define the blueprint for objects and contain properties and functions. - Objects are instances of classes that have state in their properties and behavior through functions. Multiple objects can be created from a class. - Constructors initialize an object's properties. Primary constructors are defined in the class header while secondary constructors use the constructor keyword. - Nested classes are declared within other classes while inner classes use the inner keyword and can access private members of outer classes

Uploaded by

subbareddy
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 74

Kotlin OOPs

 Class and Object


 Nested and Inner Class
 Kotlin Constructor
 Visibility Modifier
 Kotlin Inheritance
 Abstract Class
 Kotlin Interface
 Data Class
 Sealed Class
 Extension Function
 Kotlin Generics

Kotlin Class and Object


Kotlin supports both object oriented programming (OOP) as well as functional
programming. Object oriented programming is based on real
time objects and classes. Kotlin also support pillars of OOP language such as
encapsulation, inheritance and polymorphism.

Kotlin Class
Kotlin class is similar to Java class, a class is a blueprint for the objects which
have common properties. Kotlin classes are declared using keyword class.
Kotlin class has a class header which specifies its type parameters, constructor
etc. and the class body which is surrounded by curly braces.

Syntax of Kotlin class declaration

class className{   // class header  

      // property  

      // member function  

}  
In above example, class className is an empty constructor. It is generated by
compiler automatically but if we want to provide a constructor, we need to write
a constructor keyword followed by class name as:

class className constructor(){   // class header  

      // property  

      // member function  

}  

Example of Kotlin class


class account {  

var acc_no: Int = 0  

var name: String? = null  

var amount: Float = 0f  

  

    fun deposit() {  

        //deposite code  

    }  

  

    fun withdraw() {  

       // withdraw code  

    }  

  

    fun checkBalance() {  
        //balance check code  

     }  

  

}  

The account class has three properties acc_no, name, amount and three member
functions deposit(), withdraw(),checkBalance().

In Kotlin, property must be initialize or declare as abstract. In above class,


properties acc_no initialize as 0, name as null and amount as 0f.

Kotlin Object
Object is real time entity or may be a logical entity which has state and
behavior. It has the characteristics:

state: it represents value of an object.

behavior: it represent the functionality of an object.

Object is used to access the properties and member function of a class. Kotlin
allows to create multiple object of a class.

Create an object

Kotlin object is created in two steps, the first is to create reference and then
create an object.

var obj1 = className()  

Creating multiple object

var obj1 = className()  

var obj2 = className()  

Here obj1 and obj2 are reference and className() is an object.

Access class property and member function


Properties and member function of class are accessed by . operator using object.
For example:

obj.deopsit()  

obj.name = Ajay   

Let's create an example, which access the class property and member function
using . operator.

class Account {  

    var acc_no: Int = 0  

    var name: String =  ""  

    var amount: Float = 0.toFloat()  

    fun insert(ac: Int,n: String, am: Float ) {  

        acc_no=ac  

        name=n  

        amount=am  

        println("Account no: ${acc_no} holder :${name} amount :${amount}")  

    }  

  

    fun deposit() {  

        //deposite code  

    }  

  

    fun withdraw() {  
       // withdraw code  

    }  

  

    fun checkBalance() {  

        //balance check code  

     }  

  

}  

fun main(args: Array<String>){  

    Account()  

    var acc= Account()  

    acc.insert(832345,"Ankit",1000f) //accessing member function  

    println("${acc.name}") //accessing class property  

}  

Output:

Account no: 832345 holder :Ankit amount :1000.0

Ankit

Kotlin Nested class and Inner class


Kotlin Nested class
Nested class is such class which is created inside another class. In Kotlin, nested
class is by default static, so its data member and member function can be
accessed without creating an object of class. Nested class cannot be able to
access the data member of outer class.

class outerClass{  

   //outer class code  

    class nestedClass{  

      //nested class code  

    }  

}  

Kotlin Nested Class Example

class outerClass{  

    private var name: String = "Ashu"  

    class nestedClass{  

var description: String = "code inside nested class"  

        private var id: Int = 101  

        fun foo(){  

          //  print("name is ${name}") // cannot access the outer class member  

println("Id is ${id}")  

        }  

    }  

}  

fun main(args: Array<String>){  

// nested class must be initialize  
println(outerClass.nestedClass().description) // accessing property  

var obj = outerClass.nestedClass() // object creation  

    obj.foo() // access member function  

}  

Output:

code inside nested class

Id is 101

Kotlin Inner class

Inner class is a class which is created inside another class with keyword inner.
In other words, we can say that a nested class which is marked as "inner" is
called inner class.

Inner class cannot be declared inside interfaces or non-inner nested classes.

class outerClass{  

   //outer class code  

    inner class innerClass{  

      //nested class code  

    }  

}  

The advantage of inner class over nested class is that, it is able to access
members of outer class even it is private. Inner class keeps a reference to an
object of outer class.

Kotlin Inner Class Example

class outerClass{  
     private  var name: String = "Ashu"  

     inner class  innerClass{  

var description: String = "code inside inner class"  

        private var id: Int = 101  

       fun foo(){  

println("name is ${name}") // access the outer class member even private  

println("Id is ${id}")  

        }  

    }  

}  

fun main(args: Array<String>){  

println(outerClass().innerClass().description) // accessing property  

var obj = outerClass().innerClass() // object creation  

    obj.foo() // access member function  

  

}  

Output:

code inside inner class

name is Ashu

Id is 101
Kotlin Constructor
In Kotlin, constructor is a block of code similar to method. Constructor is
declared with the same name as the class followed by parenthesis '()'.
Constructor is used to initialize the variables at the time of object creation.

Types of Kotlin constructors


There are two types of constructors in Kotlin:

1. Primary constructor
2. Secondary constructor

There is only one primary constructor in a Kotlin class whereas secondary


constructor may be one or more.

Kotlin primary constructor

Primary constructor is used to initialize the class. It is declared at class header.


Primary constructor code is surrounded by parentheses with optional parameter.

Let's see an example of declaration of primary constructor. In the below code,


we declare a constructor myClass with two parameter name and id. Parameter
name is only read property whereas id is read and write property.

class myClass(valname: String,varid: Int) {  

    // class body  

}  

When the object of myClasss is created, it initializes name and id with "Ashu"
and "101" respectively.

class myClass(val name: String, var id: Int) {  

}  

fun main(args: Array<String>){  

val myclass = myClass ("Ashu", 101)  
  

println("Name = ${ myclass.name}")  

println("Id = ${ myclass.id}")  

}  

Output:

Name = Ashu

Id = 101

Primary constructor with initializer block

The primary constructor does not contain any code. Initializer blocks are used to
initialization of code. This block is prefixed with init keyword. At the period of
instance initialization, the initialized blocks are executed in the same order as
they appear in class body.

Let's rewrite the above code using initialize block:

class myClass(name: String, id: Int) {  

val e_name: String  

var e_id: Int  

init{  

e_name = name.capitalize()  

e_id = id  

  

println("Name = ${e_name}")  

println("Id = ${e_id}")  

    }  
}  

fun main(args: Array<String>){  

val myclass = myClass ("Ashu", 101)  

  

}  

Output:

Name = Ashu

Id = 101

In above code, parameters name and id accept values "Ashu" and "101" when


myclass object is created. The properties name and id are used without "val" or
"var", so they are not properties of myClass class.

When object of myClass class is created, it executes initializer block which


initializese_name and e_id.

Kotlin secondary constructor

In Kotlin, secondary constructor can be created one or more in class. The


secondary constructor is created using "constructor" keyword.

Let's see an example of declaration of secondary constructor. In the below code,


we declare two constructor of myClass with two parameter name and id.

class myClass{  

  

    constructor(id: Int){  

        //code   

    }  

    constructor(name: String, id: Int){  
        //code   

    }  

}  

Let's see an example of secondary constructor assigning the value while object
of class is created.

class myClass{  

  

    constructor(name: String, id: Int){  

println("Name = ${name}")  

println("Id = ${id}")  

    }  

}  

fun main(args: Array<String>){  

val myclass = myClass ("Ashu", 101)  

  

}  

Output:

Name = Ashu

Id = 101

We can also use both primary as well as secondary constructor in a same class.
By using primary as well secondary constructor in same class, secondary
constructor needs to authorize to primary constructor. Authorization to another
constructor in same class is done using this() keyword.
AD

For example:

class myClass(password: String){  

  

    constructor(name: String, id: Int, password: String): this(password){  

println("Name = ${name}")  

println("Id = ${id}")  

println("Password = ${password}")  

    }  

}  

fun main(args: Array<String>){  

val myclass = myClass ("Ashu", 101, "mypassword")  

  

}  

Output:

Name = Ashu

Id = 101

Password = mypassword

Calling one secondary constructor from another secondary constructor of same


class

In Kotlin, one secondary constructor can call another secondary constructor of


same class. This is done by using this() keyword.
For example:

class myClass{  

  

    constructor(name: String, id: Int): this(name,id, "mypassword"){  

println("this executes next")  

println("Name = ${name}")  

println("Id = ${id}")  

    }  

  

    constructor(name: String, id: Int,pass: String){  

println("this executes first")  

println("Name = ${name}")  

println("Id = ${id}")  

println("Password = ${pass}")  

    }  

}  

fun main(args: Array<String>){  

val myclass = myClass ("Ashu", 101)  

  

}  

Output:
AD

this executes first

Name = Ashu

Id = 101

Password = mypassword

this executes next

Name = Ashu

Id = 101

AD

Calling supper class secondary constructor from derived class secondary


constructor

In Kotlin, one derived class secondary constructor can call the base class
secondary constructor. This is done using super keyword, this is the concept of
inheritance.

open class Parent{  

  

    constructor(name: String, id: Int){  

println("this executes first")  

println("Name = ${name}")  

println("Id = ${id}")  

    }  

  

    constructor(name: String, id: Int,pass: String){  
println("this executes third")  

println("Name = ${name}")  

println("Id = ${id}")  

println("Password = ${pass}")  

    }  

}  

class Child: Parent{  

    constructor(name: String, id: Int): super(name,id){  

println("this executes second")  

println("Name = ${name}")  

println("Id = ${id}")  

    }  

  

   constructor(name: String, id: Int,pass: String):super(name,id,"password"){  

println("this executes forth")  

println("Name = ${name}")  

println("Id = ${id}")  

println("Password = ${pass}")  

    }  

}  

fun main(args: Array<String>){  
val obj1 = Child("Ashu", 101)  

val obj2 = Child("Ashu", 101,"mypassword")  

}  

Output:

this executes first

Name = Ashu

Id = 101

this executes second

Name = Ashu

Id = 101

this executes third

Name = Ashu

Id = 101

Password = password

this executes forth

Name = Ashu

Id = 101

Password = mypassword
Kotlin Visibility Modifier

Visibility modifiers are the keywords which are used to restrict the use of class,
interface, methods, and property of Kotlin in the application. These modifiers
are used at multiple places such as class header or method body.

In Kotlin, visibility modifiers are categorized into four different types:

public

protected

internal

private

public modifier

A public modifier is accessible from everywhere in the project. It is a default


modifier in Kotlin. If any class, interface etc. are not specified with any access
modifier then that class, interface etc. are used in public scope.

public class Example{  

}  

class Demo{  

}  

public fun hello()  

fun demo()  

public val x = 5  

val y = 10  

All public declaration can be placed at top of the file. If a member of class is not
specified then it is by default public.

protected modifier
A protected modifier with class or interface allows visibility to its class or
subclass only. A protected declaration (when overridden) in its subclass is also
protected modifier unless it is explicitly changed.

open class Base{  

    protected val i = 0  

}  

  

class Derived : Base(){  

  

    fun getValue() : Int  

    {  

        return i  

    }  

}  

In Kotlin, protected modifier cannot be declared at top level.

Overriding of protected types

open class Base{  

  open protected val i = 5  

}  

class Another : Base(){  

    fun getValue() : Int  

    {  
        return i  

    }  

    override val i =10  

}  

internal modifier

The internal modifiers are newly added in Kotlin, it is not available in Java.


Declaring anything makes that field marked as internal field. The internal
modifier makes the field visible only inside the module in which it is
implemented.

internal class Example{  

    internal val x = 5  

    internal fun getValue(){  

  

    }  

}  

internal val y = 10  

In above, all the fields are declared as internal which are accessible only inside
the module in which they are implemented.

AD

private modifier

A private modifier allows the declaration to be accessible only within the block


in which properties, fields, etc. are declare. The private modifier declaration
does not allow to access the outside the scope. A private package can be
accessible within that specific file.

private class Example {  
    private val x = 1  

     private valdoSomething() {  

    }  

}  

In above class Example,val x and function doSomthing() are declared as private.


The class "Example" is accessible from the same source file, "val x" and "fun
doSomthing()" are accessible within Example class.

Example of Visibility Modifier

open class Base() {  

var a = 1 // public by default  

    private var b = 2 // private to Base class  

    protected open val c = 3  // visible to the Base and the Derived class  

    internal val d = 4 // visible inside the same module  

    protected fun e() { } // visible to the Base and the Derived class  

}  

  

class Derived: Base() {  

    // a, c, d, and e() of the Base class are visible  

    // b is not visible  

    override val c = 9 // c is protected  

}  

  
fun main(args: Array<String>) {  

val base = Base()  

    // base.a and base.d are visible  

    // base.b, base.c and base.e() are not visible  

val derived = Derived()  

    // derived.c is not visible  

}  

Kotlin Inheritance
Inheritance is an important feature of object oriented programming language.
Inheritance allows to inherit the feature of existing class (or base or parent class)
to new class (or derived class or child class).

The main class is called super class (or parent class) and the class which inherits
the superclass is called subclass (or child class). The subclass contains features
of superclass as well as its own.

The concept of inheritance is allowed when two or more classes have same
properties. It allows code reusability. A derived class has only one base class but
may have multiple interfaces whereas a base class may have one or more
derived classes.

In Kotlin, the derived class inherits a base class using: operator in the class
header (after the derive class name or constructor)

open class Base(p: Int){  

  

}  

class Derived(p: Int) : Base(p){  
  

}  

Suppose that,we have two different classes "Programmer" and "Salesman"


having the common properties 'name','age', and 'salary' as well as their own
separate functionalitiesdoProgram() and fieldWork(). The feature of inheritance
allows that we can inherit (Employee) containing the common features.

open class Employee(name: String, age: Int, salary: Float) {  

    // code of employee  

}  

  

class Programmer(name: String, age: Int, salary: Float): Employee(name,age,sal
ary) {  

    // code of programmer  

}  

  

class Salesman(name: String, age: Int, salary: Float): Employee(name,age,salary
) {  

    // code of salesman  

}  

All Kotlin classes have a common superclass "Any". It is a default superclass for
a class with no supertypes explicitly specified.

For example, a class Example is implicitly inherited from Any.

class Example  

Kotlin open keyword


As Kotlin classes are final by default, they cannot be inherited simply. We use
the open keyword before the class to inherit a class and make it to non-final,

For example:

open class Example{  

// I can now be extended!  

}  

Kotlin Inheriting fields from a class

When we inherit a class to derive class, all the fields and functionalities are
inherited. We can use these fields and functionalities in derived class.

For example:

open class Base{  

val x = 10  

}  

class Derived: Base() {  

    fun foo() {  

println("x is equal to " + x)  

    }  

}  

fun main(args: Array<String>) {  

val derived = Derived()  

    derived.foo()   

}  
Output:

x is equal to 10

Kotlin Inheriting methods from a class

open class Bird {  

    fun fly() {  

println("flying...")  

    }  

}  

class Duck: Bird() {  

    fun swim() {  

println("swimming...")  

    }  

}  

fun main(args: Array<String>) {  

val duck = Duck()  

    duck.fly()   

duck.swim()  

}  

Output:

flying...

swimming...

Kotlin Inheritance Example


Here, we declare a class Employee is superclass and Programmer and Salesman
are their subclasses. The subclasses inherit properties name, age and salary as
well as subclasses containtheir own functionalitieslike doProgram() and
fieldWork().

open class Employee(name: String, age: Int, salary: Float) {  

init {  

println("Name is $name.")  

println("Age is $age")  

println("Salary is $salary")  

    }  

}  

class Programmer(name: String, age: Int, salary: Float):Employee(name,age,sala
ry){  

    fun doProgram() {  

println("programming is my passion.")  

    }  

}  

class Salesman(name: String, age: Int, salary: Float):Employee(name,age,salary)
{  

    fun fieldWork() {  

println("travelling is my hobby.")  

    }  

}  

fun main(args: Array<String>){  
val obj1 = Programmer("Ashu", 25, 40000f)  

    obj1.doProgram()  

val obj2 = Salesman("Ajay", 24, 30000f)  

    obj2.fieldWork()  

}  

Output:

Name is Ashu.

Age is 25

Salary is 40000.0

programming is my passion.

Name is Ajay.

Age is 24

Salary is 30000.0

travelling is my hobby.

AD

Kotlin Inheritance and primary constructor

If the base and derived class both having primary constructor in that case the
parameters are initialized in the primary constructor of base class. In above
example of inheritance, all classes contain three parameters "name", "age" and
"salary" and all these parameters are initialized in primary constructor of base
class.

When a base and derived class both contains different numbers of parameters in
their primary constructor then base class parameters are initialized form derived
class object.
AD

For example:

open class Employee(name: String,salary: Float) {  

init {  

println("Name is $name.")  

println("Salary is $salary")  

    }  

}  

class Programmer(name: String, dept: String, salary: Float):Employee(name,sala
ry){  

init {  

println("Name $name of department $dept with salary $salary.")  

    }  

    fun doProgram() {  

println("Programming is my passion.")  

  

    }  

}  

class Salesman(name: String, dept: String, salary: Float):Employee(name,salary)
{  

init {  

println("Name $name of department $dept with salary $salary.")  
    }  

    fun fieldWork() {  

println("Travelling is my hobby.")  

  

    }  

}  

fun main(args: Array<String>){  

val obj1 = Programmer("Ashu", "Development", 40000f)  

    obj1.doProgram()  

println()  

val obj2 = Salesman("Ajay", "Marketing", 30000f)  

    obj2.fieldWork()  

}  

Output:

Name is Ashu.

Salary is 40000.0

Name Ashu of department Development with salary 40000.0.

Programming is my passion.

Name is Ajay.

Salary is 30000.0
Name Ajay of department Marketing with salary 30000.0.

Travelling is my hobby.

When an object of derived class is created, it calls its superclass first and
executes init block of base class followed by its own.

Kotlin Inheritance and secondary constructor

If derived class does not contain any primary constructor then it is required to
call the base class secondary constructor from derived class
using super keyword.

For example,

AD

open class Patent {  

  

    constructor(name: String, id: Int) {  

println("execute super constructor $name: $id")  

    }  

}  

  

class Child: Patent {  

  

    constructor(name: String, id: Int, dept: String): super(name, id) {  

        print("execute child class constructor with property $name, $id, $dept")  

    }  

}  
fun main(args: Array<String>) {  

val child = Child("Ashu",101, "Developer")  

}  

Output:

execute super constructor Ashu: 101

execute child class constructor with property Ashu, 101, Developer

In above example, when object of Child class is created, it calls its constructor
and initializes its parameters with values "Ashu", "101" and "Developer". At the
same time Child class constructor calling its supper class constructor using super
keyword with values of name and id. Due to the presence of super keyword
thebody of superclass constructor executes first and returns to Child class
constructor.

Kotlin Method Overriding


Method overriding means providing the specific implementation of method of
super (parent) class into its subclass (child) class.

In other words, when subclass redefines or modifies the method of its superclass
into subclass, it is known as method overriding. Method overriding is only
possible in inheritance.

KotlinRules of method overriding

Parent class and its method or property which is to be overridden must be open
(non-final).

Method name of base class and derived class must have same.

Method must have same parameter as in base class.

Example of inheritance without overriding

open class Bird {  

    open fun fly() {  
println("Bird is flying...")  

    }  

}  

class Parrot: Bird() {  

  

}  

class Duck: Bird() {  

  

}  

fun main(args: Array<String>) {  

val p = Parrot()  

    p.fly()  

val d = Duck()  

    d.fly()  

}  

Output:

Bird is flying...

Bird is flying...

In above example, a program without overriding the method of base class we


found that both derived classes Parrot and Duck perform the same common
operation. To overcome with this problem we use the concept of method
overriding.

Example of Kotlin method overriding


In this example, the method fly() of parent class Bird is overridden in its
subclass Parrot and Duck. To override the method of parent class, the parent
class and its method which is going to override must be declare as open. At the
same time method which is overridden in child class must be prefaced with
keyword override.

open class Bird {  

    open fun fly() {  

println("Bird is flying...")  

    }  

}  

class Parrot: Bird() {  

    override fun fly() {  

println("Parrot is flying...")  

    }  

}  

class Duck: Bird() {  

    override fun fly() {  

println("Duck is flying...")  

    }  

}  

fun main(args: Array<String>) {  

val p = Parrot()  

    p.fly()  
val d = Duck()  

    d.fly()  

}  

Output:

Parrot is flying...

Duck is flying...

Example of Kotlin property overriding

Property of superclass can also be overridden in its subclass as similar to


method. A color property of Bird class is overridden in its
subclass Parrot and Duck and modified.

open class Bird {  

    open var color = "Black"  

    open fun fly() {  

println("Bird is flying...")  

    }  

}  

class Parrot: Bird() {  

    override var color = "Green"  

    override fun fly() {  

println("Parrot is flying...")  

    }  

}  
class Duck: Bird() {  

    override var color = "White"  

    override fun fly() {  

println("Duck is flying...")  

    }  

}  

fun main(args: Array<String>) {  

val p = Parrot()  

    p.fly()  

println(p.color)  

val d = Duck()  

    d.fly()  

println(d.color)  

}  

Output:

Parrot is flying...

Green

Duck is flying...

White

We can override the val property with var property in inheritance but vice-versa
is not true.

Kotlin superclass implementation


Derived class can also call its superclass methods and property
using super keyword.

For example:

open class Bird {  

    open var color = "Black"  

    open fun fly() {  

println("Bird is flying...")  

    }  

}  

class Parrot: Bird() {  

    override var color = "Green"  

    override fun fly() {  

        super.fly()  

println("Parrot is flying...")  

  

    }  

}  

  

fun main(args: Array<String>) {  

val p = Parrot()  

    p.fly()  

println(p.color)  
  

}  

Output:

Bird is flying...

Parrot is flying...

Green

Kotlin multiple class implementation

In Kotlin, derived class uses a supertype name in angle brackets,


e.gsuper<Base> when it implements same function name provided in multiple
classes.

For example, a derived class Parrotextends its superclass Bird and


implement Duck interface containing same function fly(). To call particular
method of each class and interface we must be mention supertype name in angle
brackets as super<Bird>.fly() and super<Duck>.fly() for each method.

open class Bird {  

    open var color = "Black"  

    open fun fly() {  

println("Bird is flying...")  

    }  

}  

interface Duck {  

     fun fly() {  

println("Duck is flying...")  

    }  
}  

class Parrot: Bird(),Duck {  

    override var color = "Green"  

    override fun fly() {  

        super<Bird>.fly()  

        super<Duck>.fly()  

println("Parrot is flying...")  

  

    }  

}  

fun main(args: Array<String>) {  

val p = Parrot()  

    p.fly()  

println(p.color)  

  

}  

Output:

Bird is flying...

Duck is flying...

Parrot is flying...
Kotlin Abstract class
A class which is declared with abstract keyword is known as abstract class. An
abstract class cannot be instantiated. Means, we cannot create object of abstract
class. The method and properties of abstract class are non-abstract unless they
are explicitly declared as abstract.

Declaration of abstract class

abstract class A {  

var x = 0  

    abstract fun doSomething()  

}  

Abstract classes are partially defined classes, methods and properties which are
no implementation but must be implemented into derived class. If the derived
class does not implement the properties of base class then is also meant to be an
abstract class.

Abstract class or abstract function does not need to annotate with open keyword
as they are open by default. Abstract member function does not contain its body.
The member function cannot be declared as abstract if it contains in body in
abstract class.

Example of abstract class that has abstract method

In this example, there is an abstract class Car that contains an abstract function


run(). The implementation of run() function is provided by its subclass Honda.

abstract class Car{  

    abstract fun run()  

}  

class Honda: Car(){  

   override fun run(){  
println("Honda is running safely..")  

   }  

}  

fun main(args: Array<String>){  

val obj = Honda()  

obj.run();  

}  

Output:

Honda is running safely..

A non-abstract open member function can be over ridden in an abstract class.

open class Car {  

    open fun run() {  

println("Car is running..")  

    }  

}  

abstract class Honda : Car() {  

    override abstract fun run()  

}  

class City: Honda(){  

    override fun run() {  

      //  TODO("not implemented") //To change body of created functions use File 
| Settings | File Templates.  
println("Honda City is running..")  

    }  

}  

fun main(args: Array<String>){  

val car = Car()  

car.run()  

val city = City()  

city.run()  

}  

Output:

Car is running..

Honda City is running..

In above example, An abstract class Honda extends the class Car and its


function run(). Honda class override the run() function of Car class.
The Honda class did not give the implementation of run() function as it is also
declared as abstract. The implementation of abstract function run() of Honda
class is provided by City class.

Example of real scenario of abstract class

In this example, an abstract class Bank that contains an abstract


function simpleInterest() accepts three parameters p,r,and t. The
class SBI and PNB provides the implementation of simpleInterest() function and
returns the result.

abstract class Bank {  

    abstract fun simpleInterest(p: Int, r: Double, t: Int) :Double  

}  
  

class SBI : Bank() {  

    override fun simpleInterest(p: Int, r: Double, t: Int): Double{  

        return (p*r*t)/100  

    }  

}  

class PNB : Bank() {  

    override fun simpleInterest(p: Int, r: Double, t: Int): Double{  

        return (p*r*t)/100  

    }  

}  

fun main(args: Array<String>) {  

var sbi: Bank = SBI()  

val sbiint = sbi.simpleInterest(1000,5.0,3)  

println("SBI interest is $sbiint")  

var pnb: Bank = PNB()  

val pnbint = pnb.simpleInterest(1000,4.5,3)  

println("PNB interest is $pnbint")  

}  

Output:

SBI interest is 150.0


PNB interest is 135.0

Kotlin Interface
An interface is a blueprint of class.Kotlin interface is similar to Java 8. It
contains abstract method declarations as well as implementation of method.

Defining Interface

An interface is defined using the keyword interface. For example:

interface MyInterface {  

val id: Int // abstract property  

    fun absMethod()// abstract method  

    fun doSomthing() {  

      // optional body  

    }  

}  

The methods which are only declared without their method body are abstract by
default.

Why use Kotlin interface?

Following are the reasons to use interface:

Using interface supports functionality of multiple inheritance.

It can be used achieve to loose coupling.

It is used to achieve abstraction.


Subclass extends only one super class but implements multiple interfaces.
Extension of parent class or interface implementation are done using (:) operator
in their subclass.

Implementing Interfaces

In this example, we are implementing the


interface MyInterface in InterfaceImp class. InterfaceImp class provides the
implementation of property id and abstract method absMethod() declared in
MyInterface interface.

interface MyInterface  {  

var id: Int            // abstract property  

    fun absMethod():String    // abstract method  

    fun doSomthing() {  

println("MyInterface doing some work")  

    }  

}  

class InterfaceImp : MyInterface {  

    override var id: Int = 101  

    override fun absMethod(): String{  

return "Implementing abstract method.."  

    }  

}  

fun main(args: Array<String>) {  

val obj = InterfaceImp()  

println("Calling overriding id value = ${obj.id}")  
obj.doSomthing()  

println(obj.absMethod())  

}  

Output:

Calling overriding id value = 101

MyInterface doing some work

Implementing abstract method..

AD

Implementing multiple interface

We can implement multiple abstract methods of different interfaces in same


class. All the abstract methods must be implemented in subclass. The other non-
abstract methods of interface can be called from derived class.

For example, creating two interface MyInterface1 and MyInterface2 with


abstract methods doSomthing() and absMethod() respectively. These abstract
methods are overridden in derive class MyClass.

interface MyInterface1 {  

    fun doSomthing()  

}  

interface MyInterface2 {  

    fun absMethod()  

}  

class MyClass : MyInterface1, MyInterface2 {  

    override fun doSomthing() {  
println("overriding doSomthing() of MyInterface1")  

    }  

  

    override fun absMethod() {  

println("overriding absMethod() of MyInterface2")  

    }  

}  

fun main(args: Array<String>) {  

val myClass = MyClass()  

myClass.doSomthing()  

myClass.absMethod()  

}  

Output:

overriding doSomthing() of MyInterface1

overriding absMethod() of MyInterface2

Resolving different Interfaces having same method overriding conflicts

Let's see an example in which interface MyInterface1 and interface


MyInterface2 both contains same non-abstract method. A class MyClass
provides the implementation of these interfaces. Calling the method of interface
using object of MyClass generates an error.

interface MyInterface1 {  

    fun doSomthing(){  

println("overriding doSomthing() of MyInterface1")  
    }  

}  

interface MyInterface2 {  

    fun doSomthing(){  

println("overriding doSomthing() of MyInterface2")  

    }  

}  

class MyClass : MyInterface1, MyInterface2 {  

  

}  

fun main(args: Array<String>) {  

val myClass = MyClass()  

myClass.doSomthing()  

}  

Output:

Kotlin: Class 'MyClass' must override public open fun doSomthing(): Unit
defined in MyInterface1 because it

inherits multiple interface methods of it

To solve the above problem we need to specify particular method of interface


which we are calling. Let's see an example below.

In below example, two interfaces MyInterface1 and MyInterface2 contain two


abstract methodsadsMethod() and absMethod(name: String) and non-abstract
method doSomthing() in both respectively. A class MyClass implements both
interface and override abstract method absMethod() and absMethod(name:
String) . To override the non-abstract method doSomthing() we need to specify
interface name with method using super
keyword as super<interface_name>.methodName().

interface MyInterface1 {  

    fun doSomthing() {  

println("MyInterface 1 doing some work")  

    }  

        fun absMethod()  

}  

interface MyInterface2 {  

    fun doSomthing(){  

println("MyInterface 2 doing some work")  

    }  

    fun absMethod(name: String)  

}  

class MyClass : MyInterface1, MyInterface2 {  

    override fun doSomthing() {  

        super<MyInterface2>.doSomthing()  

    }  

  

    override fun absMethod() {  

println("Implements absMethod() of MyInterface1")  
    }  

    override fun absMethod(n: String) {  

println("Implements absMethod(name) of MyInterface2 name is  $n")  

    }  

}  

fun main(args: Array<String>) {  

val myClass = MyClass()  

myClass.doSomthing()  

myClass.absMethod()  

myClass.absMethod("Ashu")  

}  

Output:

MyInterface 2 doing some work

Implements absMethod() of MyInterface1

Implements absMethod(name) of MyInterface2 name is Ashu

interface MyInterface1 {  

    fun doSomthing() {  

println("MyInterface 1 doing some work")  

    }  

    fun absMethod()  

}  
  

interface MyInterface2 {  

    fun doSomthing() {  

println("MyInterface 2 doing some work")  

    }  

   fun absMethod() {  

println("MyInterface 2 absMethod")  

    }  

  

}  

  

class C : MyInterface1 {  

    override fun absMethod() {  

println("MyInterface1 absMethod implementation")  

    }  

}  

  

class D : MyInterface1, MyInterface2 {  

    override fun doSomthing() {  

        super<MyInterface1>.doSomthing()  

        super<MyInterface2>.doSomthing()  
    }  

  

    override fun absMethod() {  

  

        super<MyInterface2>.absMethod()  

    }  

}  

  

fun main(args: Array<String>) {  

val d = D()  

val c = C()  

d.doSomthing()  

d.absMethod()  

c.doSomthing()  

c.absMethod()  

}  

Output:

MyInterface 1 doing some work

MyInterface 2 doing some work

MyInterface 2 absMethod

MyInterface 1 doing some work


MyInterface1 absMethod implementation

Kotlin Data class

Data class is a simple class which is used to hold data/state and contains
standard functionality. A data keyword is used to declare a class as a data class.

data class User(val name: String, val age: Int)  

Declaring a data class must contains at least one primary constructor with
property argument (val or var).

Data class internally contains the following functions:

equals(): Boolean

hashCode(): Int

toString(): String

component() functions corresponding to the properties

copy()

Due to presence of above functions internally in data class, the data class
eliminates the boilerplate code.

A compression between Java data class and Kotlin data class

If we want to create a User entry in Java using data class, it require lots of
boilerplate code.

import java.util.Objects;  

  

public class User {  

    private String name;  
    private int id;  

    private String email;  

  

    public User(String name, int id, String email) {  

        this.name = name;  

        this.id = id;  

this.email = email;  

    }  

  

    public String getName() {  

        return name;  

    }  

  

    public void setName(String name) {  

        this.name = name;  

    }  

  

    public intgetId() {  

        return id;  

    }  

  
    public void setId(int id) {  

        this.id = id;  

    }  

  

    public String getEmail() {  

        return email;  

    }  

  

    public void setEmail(String email) {  

this.email = email;  

    }  

  

    @Override  

    public boolean equals(Object o) {  

        if (this == o) return true;  

        if (!(o instanceof User)) return false;  

        User user = (User) o;  

        return getId() == user.getId() &&  

Objects.equals(getName(), user.getName()) &&  

Objects.equals(getEmail(), user.getEmail());  

    }  
  

    @Override  

    public inthashCode() {  

  

        return Objects.hash(getName(), getId(), getEmail());  

    }  

  

    @Override  

    public String toString() {  

        return "User{" +  

                "name='" + name + '\'' +  

                ", id=" + id +  

                ", email='" + email + '\'' +  

                '}';  

    }  

}  

Calling the constructor of above Java data class using the object of User class as

class MyClass{  

    public static void main(String agrs[]){  

        User u = new User("Ashu",101,"mymail@mail.com");  

System.out.println(u);  
    }  

}  

Output:

User{name='Ashu', id=101, email='mymail@mail.com'}

The above Java data class code is rewritten in Kotlin data code in single line as

data class User(var name: String, var id: Int, var email: String)  

Calling the constructor of above Kotlin data class using the object of User class
as

fun main(agrs: Array<String>) {  

val u = User("Ashu", 101, "mymail@mail.com")  

println(u)  

}  

Output:

User(name=Ashu, id=101, email=mymail@mail.com)

Requirements of data class

In order to create a data class, we need to fulfill the following requirements:

Contain primary constructor with at least one parameter.

Parameters of primary constructor marked as val or var.

Data class cannot be abstract, inner, open or sealed.

Before 1.1,data class may only implements interface. After that data classes may
extend other classes.

AD
Kotlin data class toString() methods

Kotlin data class only focuses on data rather than code implementation.

Let's see a simple program without data class. In this class, we are trying to print
the reference of Product class using its object.

class Product(varitem: String, var price: Int)  

  

fun main(agrs: Array<String>) {  

val p = Product("laptop", 25000)  

println(p)  

}  

While printing the reference of Product class, it displays the hashCode() with
class name of Product. It does not print the data.

Output:

Product@266474c2

The above program is rewritten using data class and printing the reference of


Product class and displaying the data of object. It happens because the data class
internally contains the toString() which display the string representation of
object .

data class Product(varitem: String, var price: Int)  

  

fun main(agrs: Array<String>) {  

val p = Product("laptop", 25000)  

println(p)  

}  
Output:

AD

Product(name=laptop, price=25000)

Kotlin data classequals() and hashCode()

The equal() method is used to check other object is "equal to" current object.
While doing comparison between two or more hashCode(), equals() method
returns true if the hashCode() are equal, else it returns a false.

For example, let's see an example in which a normal class comparing the two
references of same class Product having same data.

class Product(varitem: String, var price: Int)  

  

fun main(agrs: Array<String>) {  

val p1 = Product("laptop", 25000)  

val p2 = Product("laptop", 25000)  

println(p1==p2)  

println(p1.equals(p2))  

}  

In above program, reference p1 and reference p2 has different references. Due to


different reference values in p1 and p2, doing comparison displays false.

Output:

false

false

The above program is rewritten using data class, printing the reference of


Product class and displaying the data of object.
AD

The hashCode() method returns hash code for the object. The hashCode()


produce same integer result, if two objects are equal.

data class Product(varitem: String, var price: Int)  

  

fun main(agrs: Array<String>) {  

val p1 = Product("laptop", 25000)  

val p2 = Product("laptop", 25000)  

println(p1==p2)  

println(p1.equals(p2))  

}  

Output:

true

true

Kotlin data class copy() method

The data class provides a copy() method which is used to create a copy (or
colon) of object. Using copy() method, some or all properties of object can be
altered.

For example:

data class Product(var item: String, var price: Int)  

  

fun main(agrs: Array<String>) {  

val p1 = Product("laptop", 25000)  
println("p1 object contain data : $p1")  

val p2 = p1.copy()  

println("p2 copied object contains default data of p1: $p2")  

val p3 = p1.copy(price = 20000)  

println("p3 contain altered data of p1 : $p3")  

}  

Output:

p1 object contain data : Product(item=laptop, price=25000)

p2 copied object contains default data of p1: Product(item=laptop, price=25000)

p3 contain altered data of p1 : Product(item=laptop, price=20000)

Default and named arguments in data class

We can also assign the default arguments in primary constructor of data class.
These default values can be changed later on program if required.

For example:

data class Product(var item: String = "laptop", var price: Int = 25000)  

  

fun main(agrs: Array<String>) {  

val p1 = Product(price = 20000)  

println(p1)  

}  

Output:

Product(item=laptop, price=20000)
Kotlin Sealed Class

Sealed class is a class which restricts the class hierarchy. A class can be declared
as sealed class using "sealed" keyword before the class name. It is used to
represent restricted class hierarchy.

Sealed class is used when the object have one of the types from limited set, but
cannot have any other type.

The constructors of sealed classes are private in default and cannot be allowed as
non-private.

Declaration of sealed class

sealed class MyClass  

The subclasses of sealed classes must be declared in the same file in which
sealed class itself.

sealed class Shape{  

    class Circle(var radius: Float): Shape()  

    class Square(var length: Int): Shape()  

    class Rectangle(var length: Int, var breadth: Int): Shape()  

 object NotAShape : Shape()  

}  

Sealed class ensures the important of type-safety by restricting the set of types at
compile time only.

sealed class A{  

    class B : A()  

    {  
class E : A() //this works.  

    }  

    class C : A()  

init {  

println("sealed class A")  

    }  

}  

  

class D : A() //this works  

{  

class F: A() //This won't work,because sealed class is defined in another scope.  

}  

A sealed class is implicitly an abstract class which cannot be instantiated.

sealed class MyClass  

fun main(args: Array<String>)  

{  

var myClass = MyClass() //compiler error. sealed types cannot be instantiated.  

}  

Sealed class with when

Sealed classes are commonly used with when expression. As the sub classes of
sealed classes have their own types act as a case. Due to this, when
expression in sealed class covers all the cases and avoid to add else clause.
For example:

sealed class Shape{  

    class Circle(var radius: Float): Shape()  

    class Square(var length: Int): Shape()  

    class Rectangle(var length: Int, var breadth: Int): Shape()  

  //  object NotAShape : Shape()  

}  

  

fun eval(e: Shape) =  

        when (e) {  

            is Shape.Circle ->println("Circle area is ${3.14*e.radius*e.radius}")  

            is Shape.Square ->println("Square area is ${e.length*e.length}")  

            is Shape.Rectangle ->println("Rectagle area is ${e.length*e.breadth}")  

            //else -> "else case is not require as all case is covered above"  

          //  Shape.NotAShape ->Double.NaN  

        }  

fun main(args: Array<String>) {  

  

var circle = Shape.Circle(5.0f)  

var square = Shape.Square(5)  

var rectangle = Shape.Rectangle(4,5)  
  

eval(circle)  

eval(square)  

eval(rectangle)  

}  

Output:

Circle area is 78.5

Square area is 25

Rectagle area is 20

Kotlin Extension Function

Kotlin extension function provides a facility to "add" methods to class without


inheriting a class or using any type of design pattern. The created extension
functions are used as a regular function inside that class.

The extension function is declared with a prefix receiver type with method


name.

fun <class_name>.<method_name>()  

In the above declaration, <class_name> is a receiver type and the


<method_name>() is an extension function.

Example of extension function declaration and its use

In general, we call all methods from outside the class which are already defined
inside the class.In below example, a Student class declares a method
is Passed() which is called from main() function by creating the object student
of Student class.
Suppose that we want to call a method (say isExcellent()) of Student class which
is not defined in class. In such situation, we create a function (isExcellent())
outside the Student class as Student.isExcellent() and call it from the main()
function. The declare Student.isExcellent() function is known as extension
function, where Student class is known as receiver type.

class Student{  

    fun isPassed(mark: Int): Boolean{  

        return mark>40  

    }  

}  

fun Student.isExcellent(mark: Int): Boolean{  

    return mark > 90  

}  

fun main(args: Array<String>){  

val student = Student()  

val passingStatus = student.isPassed(55)  

println("student passing status is $passingStatus")  

  

val excellentStatus = student.isExcellent(95)  

println("student excellent status is $excellentStatus")  

}  

Output:

student passing status is true


student excellent status is true

The above example only demonstrates about how to declare an extension


function.

Kotlin extension function example

Let's see the real example of extension function. In this example, we are
swapping the elements of MutableList<> using swap() method. However,
MutableList<>class does not provide the swap() method internally which swap
the elements of it. For doing this we create an extension function for
MutableList<> with swap() function.

The list object call the extension function (MutableList<Int>.swap(index1: Int,


index2: Int):MutableList<Int>) using list.swap(0,2) function call. The swap(0,2)
function pass the index value of list inside MutableList<Int>.swap(index1: Int,
index2: Int):MutableList<Int>) sxtension function.

fun MutableList<Int>.swap(index1: Int, index2: Int):MutableList<Int> {  

val tmp = this[index1] // 'this' represents to the list  

    this[index1] = this[index2]  

    this[index2] = tmp  

    return this  

}  

fun main(args: Array<String>) {  

val list = mutableListOf(5,10,15)  

println("before swapping the list :$list")  

val result = list.swap(0, 2)  

println("after swapping the list :$result")  

}  
Output:

before swapping the list :[5, 10, 15]

after swapping the list :[15, 10, 5]

Extension Function as Nullable Receiver

The extension function can be defined as nullable receiver type. This nullable
extension function is called through object variable even the object value is null.
The nullability of object is checked using this == null inside the body.

Let's rewrite the above program using extension function as nullable receiver.

funMutableList<Int>?.swap(index1: Int, index2: Int): Any {  

if (this == null) return "null"  

else  {  

val tmp = this[index1] // 'this' represents to the list  

this[index1] = this[index2]  

this[index2] = tmp  

return this  

    }  

}  

fun main(args: Array<String>) {  

val list = mutableListOf(5,10,15)  

println("before swapping the list :$list")  

val result = list.swap(0, 2)  

println("after swapping the list :$result")  
}  

Output:

before swapping the list :[5, 10, 15]

after swapping the list :[15, 10, 5]

Companion Object Extensions

A companion object is an object which is declared inside a class and marked


with the companion keyword. Companion object is used to call the member
function of class directly using the class name (like static in java).

A class which contains companion object can also be defined as extension


function and property for the companion object.

Example of companion object

In this example, we call a create() function declared inside companion object


using class name (MyClass) as qualifier.

class MyClass {  

    companion object {  

        fun create():String{  

            return "calls create method of companion object"  

        }  

    }  

}  

fun main(args: Array<String>){  

val instance = MyClass.create()  

}  
Output:

AD

calls create method of companion object

Companion object extensions example

Let's see an example of companion object extensions. The companion object


extension is also being called using the class name as the qualifier.

class MyClass {  

    companion object {  

        fun create(): String {  

            return "calling create method of companion object"  

        }  

    }  

}  

fun MyClass.Companion.helloWorld() {  

println("executing extension of companion object")  

}  

fun main(args: Array<String>) {  

MyClass.helloWorld() //extension function declared upon the companion object  

}  

Output:

executing extension of companion object


Kotlin Generics
Generics are the powerful features that allow to define classes, methods, and
properties etc. which can be accessed using different types. The type differences
of classes, methods, etc. are checked at compile-time.

The generic type class or method is declared as parameterized type. A


parameterized type is an instance of generic type with actual type arguments.
The parameterized types are declared using angle brackets <> Generics are
mostly used in collections.

Advantage of Generics

Following are the key advantages of using generics:

Type-safety: Generic allows to hold only single type of object. Generic does not
allow to store other object.

Type casting is not required: There is no need to typecast the object.

Compile time checking: Generics code is checked at compile time so that it can


avoid any problems at runtime.

Let's see a problem without using the generics.

In this example, we create a Person class with primary constructor having single
parameter. Now, we want to pass the different type of data in object of Person
class (say Int type as Person(30) and String type as Person("40")). The primary
constructor of Person class accept Int type Person(30) and regrets String type
Person("40"). It generates a compile time error as type mismatch.

class Person (age:Int){  

var age: Int = age  

init {  

this.age= age  

println(age)  
    }  

}  

fun main(args: Array<String>){  

var ageInt: Person = Person(30)  

var ageString: Person = Person("30")// compile time error  

}  

To solve the above problem, we use a generic type class which is a user defined
class that accepts different type of parametersin single class.

Let's rewrite the above code using generic type. A class Person of type <T> is a
general type class that accepts both Int and String types of parameter.

In other words, the type parameter <T> is a place holder that will be replaced by
type argument. It will be replaced when the generic type is instantiated.

class Person<T>(age: T){  

var age: T = age  

init {  

this.age= age  

println(age)  

    }  

}  

fun main(args: Array<String>){  

var ageInt: Person<Int> = Person<Int>(30)  

var ageString: Person<String> = Person<String>("40")  

}  
Output:

30

40

In above example, when the object of Person class is created using type Int as
Person<Int>(30) and Person<String>("40"), it replaces the Person class of
type T with Int and String respectively.

Syntax of generic class

class_or_interface<Type>  

Syntax of generic method

<Type>methodName(parameter: classType<Type>)  

Kotlin generic example

Let's see an example of generic method. In this example, we are accessing the
generic method of collection type (ArrayList). For doing this, we create two
different objectsof ArrayList class arrayListOf<String>("Ashu","Ajay") and
arrayListOf<Float>(10.5f,5.0f,25.5f) of String and Float types respectively.
When we call the generic method <T>printValue(list: ArrayList<T>) using
printValue(stringList), the type T of method <T>printValue(list:
ArrayList<T>)will be replaced by String type. Similarly, when we call the
generic method using printValue(floatList), the type T of method
<T>printValue(list: ArrayList<T>) will replace by Float type.

fun main(args: Array<String>){  

val stringList: ArrayList<String> = arrayListOf<String>("Ashu","Ajay")  

val s: String = stringList[0]  

println("printing the string value of stringList: $s")  

printValue(stringList)  

val floatList: ArrayList<Float> = arrayListOf<Float>(10.5f,5.0f,25.5f)  
printValue(floatList)     

}  

fun <T>printValue(list: ArrayList<T>){  

    for(element in list){  

println(element)  

    }  

}  

Output:

printing the string value of stringList: Ashu

Ashu

Ajay

10.5

5.0

25.5

Kotlin generic extension function example

As extension function allows to add methods to class without inherit a class or


any design pattern.

In this example, we add a method printValue()to ArrayList class of generic type.


This method is called form stringList.printValue() and floatList.printValue()of
String and Float types respectively. As "this" keyword in extension function
represent the current calling instance. When we call the extension function using
stringList.printValue(), the this represents stringList instance containing String
type values. Similarly, calling the extension function using
floatList.printValue(), the this represents floatList instance containing Float type
values.
fun main(args: Array<String>){  

val stringList: ArrayList<String> = arrayListOf<String>("Ashu","Ajay")  

stringList.printValue()  

val floatList: ArrayList<Float> = arrayListOf<Float>(10.5f,5.0f,25.5f)  

floatList.printValue()  

}  

fun <T>ArrayList<T>.printValue(){  

    for(element in this){  

println(element)  

    }  

}  

Output:

AD

Ashu

Ajay

10.5

5.0

25.5

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy