JavaScript

OOP

Dagens lektion

  • Introduktion till OOP
  • Prototype & Prototype inheritance
  • This-nykelordet
  • New-nykelordet
  • ES6 Klasser

Syfte

  • Få grundläggande teoretiska kunskaper om OOP generellt
  • Förstå hur OOP implementeras i JavaScript
  • Få grundläggande kunskaper om prototype och protoype inheritance i JavaScript
  • Få grundläggande kunskaper om ES6 classes för framtida användning av OOP

PROGRAMMERINGSPARADIGM

  • Ju större program man har, desto mer komplex blir den att underhålla. Där används programmeringsparadigm för att lösa problemet!
  • Ett programmeringsparadigm är ett grundläggande tillvägagångssätt för att strukturera och skapa programvarukod.
  • Exempelvis funktionell programmering, där funktioner används för att skapa logik.
  • OOP är ett av många programmeringsparadigm, men är den mest kända och använda idag.
  • JavaScript benämns som ett multiparadgimsspråk. Vanliga paradigm inom JS är funktionell- och objektorienterad programmering

Introduktion til  objekt-orienterad programmering (OOP)

(oavsett programspråk)

OBJEKT-ORIENTERAD PROGRAMMERING (OOP)

  • OOP är ett programmeringsparadigm som syftar till att efterlikna "verkligheten" kring konceptet objekt
  • Precis som den reella världen består av verkliga objekt så använder man sig av objekt för att abstrahera en modell av verkligheten.
  • Ett objekt har/tilldelas olika egenskaper (properties) och metoder (methods)
  • (En metod är benämningen av en funktion som tillhör en klass)
  • En beskrivning, en mall över ett objekts egenskaper och metoder kallas för klass (class)
  • OOP utvecklades i syfte att organisera koden, för att bli mer strukturerad och  lättare att underhålla.

ELI5 OOP

Föreställ dig en katt.

Troligtvis tänker du på en katt med ganska många egenskaper. Kanske att den har...

en svans?

fluffig?

färg?

bra balans?

ELI5 OOP

Men också att den har beteenden som...

hoppa?

jama?

Detta är precis vad objekt är. Men i programmering väljer vi själva hur objektet ska vara eller bete sig.

KATT

Färg

Fluffig

Bra balans

En svans

Kan jama

Kan hoppa

Mallen (beskrivningen)  för vår katt.

Kallas KLASS

Ett objekt skapas utifrån en klass.

KATT

new Katt()

new Katt()

new Katt()

new Katt()

INSTANS

INSTANS

INSTANS

INSTANS

Så länge man har mallen (klassen) kan man skapa hur många instanser som helst!

KLASSER OCH INSTANSER

Class User

{ 
  PROPERTIES:
  username
  password
  email

  METHODS:
  login(username, pwd) {
  //Logisk för login
  }

  createPost(str) {
  // Logik för att 
  // skapa inlägg
  }
}

Instans

{ 
  PROPERTIES:
  username = "Fritioff"
  password = "123"
  email = fritt@tech.com


  METHODS:
  login(username, pwd) {
  //Logisk för login
  }

  createPost(str) {
  // Logik för att 
  // skapa inlägg
  }
}

Instans

{ 
  PROPERTIES:
  username = "Barbara"
  password = "456"
  email = barba@tech.com


  METHODS:
  login(username, pwd) {
  //Logisk för login
  }

  createPost(str) {
  // Logik för att 
  // skapa inlägg
  }
}

new User()

new User()

4 PRINCIPER I OOP

Abstraktion

Inkapsling

Arv

Polymorphism

ABSTRAKTION

Att skapa en enkel modell av något mer komplext och endast
visa det som behövs för att interagera med objektet.

 

Abstraktion i OOP döljer detaljer och visar endast det
nödvändiga av ett objekt vilket resulterar i ett enklare interface
till objektet.

ABSTRAKTION

DU

MOBIL

Home knapp

Volym

Ladda mobil

Det räcker att du kan styra några "inputs", inte styra all funktionalitet som finns i mobilen.

INKAPSLING

Processen som involverar att organisera funktioner och variabler i
separata enheter. Där en enhet inom OOP är ett objekt.


Ett objekt inom OOP kallas variabler för egenskaper och funktioner
kallas istället metoder

Klass

Metoder

Egenskaper

INKAPSLING

Skillnad

let salary = 25000;
let overtime = 15;
let rate = 100;

function getMonthlyWage(salary, overtime, rate) {
  return salary + (overtime * rate);
 
}

getMonthlyWage(salary, overtime, rate);

Procedurell, ej inkapsling i JS

INKAPSLING

Skillnad

let employee = {
  salary: 25000,
  overtime: 15,
  rate: 100,
  getMonthlyWage() {
    return this.salary + (this.overtime * this.rate)
  }
};

employee.getMonthlyWage();

Exempel på inkapsling i JS

(men vi kommer senare till hur det görs mer konkret för OOP i JS)

ARV

För att inte upprepa oss i kod kan vi låta objekt ärva egenskaper
och metoder från andra objekt


Mantra: Don’t Repeat Yourself !

Object

Number

String

Integer

Animal

Fish

Bird

Eagle

Parrot

ARV

Class User

{ 
  PROPERTIES:
  username
  password
  email

  METHODS:
  login(username, pwd) {
  //Logisk för login
  }

  createPost(str) {
  // Logik för att 
  // skapa inlägg
  }
}

Class Admin

{ 
  PROPERTIES:
  username 
  password 
  email
  permissions


  METHODS:
  login(username, pwd) {
  //Logisk för login
  }

  createPost(str) {
  // Logik för att 
  // skapa inlägg
  }
  
  deleteUser(user) {
  // Logik för att ta bort
  }
}

Klass Admin delar samma egenskaper och metoder och skulle kunna ärva från User

PARENT

CHILD

POLYMORPHISM

Hänvisar till att olika typer av objekt kan implementera samma
egenskap och/eller metoder men att de också kan implementera
egna specifika varianter av dessa.

 

OOP i JavaScript

Hur implementeras OOP i Javascript?

  • JavaScript är inte ett OOP-språk i grunden. Till skillnad från Java, C# eller C++. Men den stödjer OOP, speciellt efter ES6
  • Istället är Javascript ett prototyp-baserat språk
  • Med ES6 ville man locka utvecklare och underlätta för dem. Då introducerades flera olika koncept som underlättar arbetet utifrån ett OOP-arbetssätt. T.ex ES6 Classes, constructor och objekt

OOP i JavaScript

  • Klasser: Mallen som skapar objekt där metoder och egenskaper ingår.
  • Objekt: En instans av en klass.
  • Egenskaper: Information som objektet lagrar och kan använda sig av inom metoderna
  • Metoder: Något ska hände nära man anropar metoden på instansen
  •  Konstruktor: En metod som körs automatiskt när ett objekt skapas och används för att initiera objektets egenskaper.
  • Arv: Arv låter en klass ärva egenskaper och metoder från en annan klass.

Prototype och Prototype inheritance

Exempel Array Prototype

const num = [7, 11, 13]

num.map(element => element * 10)

Array.prototype är prototypen för alla array-objekt vi skapar i Javascript. Därför kan alla arrays som skapas få åtkomst till map() och fler som finns i denna prototype.

  • I princip allt inom JS är ett objekt. T.ex funktioner och arrayer
  • Alla objekt har en egenskap som kallas för "prototype", som själv är ett objekt.
  • När nya objekt skapas (t.ex en array) ärver den metoder och egenskaper från prototype-objektet. (Array.prototype). Det kallas "Prototype inheritance"
  • Eftersom "prototype" själv är ett objekt så har den sin egen prototype som slutar med "Object.prototype" detta kallas för Prototype chain

Prototype i JavaScript

 

Kodexempel med prototype

KLASSISK OOP MED KLASSER

OOP i JS med PROTOTYPES

KLASS

INSTANS

OBJEKT

PROTOTYPE

Innehåller metoder

Får åtkomst till metoderna

"Prototypal inheritance": Prototypen har metoder som är åtkomliga till alla objekt som är länkat till den prototypen

-> Hur kan vi skapa nya objekt (instanser) utan att använda oss av "klassiska" klasser?

-> Hur kan vi länka objekt till en prototype så att den kan delas med alla instanser från det objektet?

Men hur efterliknar vi OOP i JS?

 3 sätt att implementera Prototype inheritance i JS

  1. Konstructor funktion

  2. ES6 Classes

  3. Object.create

 

👈

👈

Testar denna del för

grundförståelse

Sen all-in för detta sätt

Constructor, this och new

"This"-nykelordet

this i JavaScript är ett nyckelord som används för att referera till det kontextuella objektet inom en funktion. Beteendet för this varierar beroende på hur funktionen anropas:
 

  • Global Scope: När "this" anropar från en global funktion så refererar den till "window"-objektet i en webbläsare.
  • Constructor Function": This refererar till det nya objektet som skapas. (med "new"-nykelordet".)

Constructor och New

Vi använder oss av en funktion och specificerar olika egenskaper som vi "binder" till this. När funktionen/objektet intansieras med det reserverade ordet new skapas ett nytt objekt egenskaperna bundna till this kommer höra till objektet.

function Person(name, age) {
  this.name = name
  this.age = age
}

const person1 = new Person("Tim", 31)
const person2 = new Person("Tommy", 32)

console.log(person1.name) // Tim
console.log(person2.age) // 32

OOP gamla sättet med prototype

Varje objekt/funktion som skapas har en Prototype. Därför kan vi alltså lägga till metoder/funktioner på dess Prototype!

function Person(name, age) {
  this.name = name
  this.age = age
}

Person.prototype.sayHello = function() {
    return "Hello, " + this.name;
};

const person1 = new Person("Tim", 31)

console.log(person1.sayHello())

Testa själv JS-OOP the old way

  1. Konstruktorfunktion Song:  Skapa en konstruktorfunktion Song som initieras med egenskaper som title, artist, och duration.
  2. Metod playSong: Lägg till en metod playSong som skriver ut "Playing [title] by [artist]".
  3. Skapa Instanser: Skapa två instanser av Song, till exempel en låt med titeln "Happy" av "Pharrell" och en annan med titeln "Imagine" av "John Lennon".
  4. Anropa playSong: Anropa playSong på båda instanserna och verifiera att utskriften är korrekt.

Prototype Inheritance

Varje metod/egenskap som läggs till på ett objekts prototyp kommer att vara åtkomlig till alla instanser som är länkade till den prototypen. Det görs genom __proto__.

Person

Person

Prototype

Tim

Tommy

.constructor

.prototype

__proto__

ES6 Classes

Det nya sättet som liknar hur OOP skrivs i andra språk!

Använd dig av detta, men kom ihåg att prototype och protoype inheritance är det underliggande sättet!

ES6 Classes

Endast en omskrivning, syntaxtiskt socker för att efterlikna syntax i andra objektorienterade programspråk.

class Person {

  constructor(name, age) {
    this.name = name
    this.age = age
  }
  
  sayHello = function() {
    return "Hello, " + this.name;
 }
}

const person1 = new Person("Tim", 31)
console.log(person1.sayHello())

Konstrukurn

Med hjälp av en konstruktor så kan vi låta vissa värden i vårt
objekt sättas direkt när objektet skapas vilket kan vara väldigt
användbart. En konstruktor kan även innehålla en metod som anropas när objektet skapas. En konstruktor kan utelämnas, då skapas endast ett tomt objekt.

class Polygon { 
  constructor(height, width) { 
     this.h = height; 
     this.w = width;
  } 
  showPolygon() { 
     console.log(`The height of the polygon ${this.h} and width ${this.h}`) 
  } 
}

Skapa den underliggande koden för ett receptprogram.

Skapa en klass som representerar recept.
Varje recept ska ha: - titel - beskrivning  -
tidsåtgång - ingredienslista (array []) - tillredningssteg
(array[])


Det ska finnas en konstruktor och ett antal metoder för att
pusha/poppa in nya element till arrayerna. Man kan även lägga till
t.ex. en metod som skriver ut allt som har med receptet att göra
e.g. printRecipe. Kom även på övriga metoder som skulle kunna läggas till

Exempel

Statiska metoder

Statiska metoder defineras på klassen. Man anropar en statisk metod genom att använda klassnamnet, inte instansobjektet. Man använder det reserverade ordet static för att ange om metoden eller egenskapen är static. Man behöver alltså inte skapa ett nytt objekt för att använda funktionen (konstruktorn "hoppas" över)

Använda en statisk metod

# JS OOP
class Square {
    constructor(side) {
        this.side = side;
    }
    findPerimeter() {
        return 4 * this.side;
    }
    
    static comparePerimeter(square1, square2) {
        if (square1.side > square2.side) {
            console.log("First square has more perimeter");
        } else if (square1.side < square2.side) {
            console.log("Second square has more perimeter");
        } else {
            console.log("Both have same perimeter");
        }

    }

}

let square1 = new Square(3);
let square2 = new Square(7);
Square.comparePerimeter(square1, square2);

Lite fördjupning...

Ingår ej i inlämningsuppgiften

Klasser med arv

Genom att använda extends ärvs en klass metoder från en klass till en annan
klass. Den ärvda klassen kan innehålla fler egenskaper utöver de som är specifika för den klassen. Genom att anropa metoden super() i Child klassen anropar vi förälderns konstruktormetod och får tillgång till förälderns (måste användas) egenskaper och metoder.

class Car {
  constructor(brand) {
    this.carname = brand;
  }
  present() {
    return 'I have a ' + this.carname;
  }
}

class Model extends Car {
  constructor(brand, model) {
    super(brand);
    this.model = model;
  }
  show() {
    return this.present() + ', it is a ' + this.model;
  }
}

const mycar = new Model("Ford", "Mustang");
# PRESENTING CODE

 Klass med arv (extend och super)

Setters and Getters

Getters och Setters används ofta i Klasser. Om du vill lägga till
getters och setters i klassen använder du nyckelorden get och set.

class Car {
  constructor(brand) {
  	this.carname = brand;
  }
  get carName() {
  	return this.carname;
  }
  set carNme(x) {
  	this.carname = x;
  }
}

Varför används get och set?

Getters och setters används kunna komma
åt egenskaper som vi sätter vill ska vara privata (inkapslade). D.v.s vi ändrar inte på själva objektet utan använder get- och setmetoder som är publika men som har åtkomsta att modifiera privat data.

Privata fält och metoder

Ett ganska nytt tillägg till JavaScript är möjligheten att lägga in
privata egenskaper och metoder i dina klasser. Dessa går enbart
att komma åt inuti klassen eller om det är egenskaper kan vi
komma åt dem med getters och setters.

class ClassWithPrivate {
  #privateField;
  #privateFieldWithInitializer = 42;
  #privateMethod() {
  // ...
  }
}

För att göra en egenskap eller metod privat lägger du helt enkelttill # innan namnet.

JavaScript OOP

By sandra-larsson

JavaScript OOP

  • 109