TypeScript Classes - Objektorientierte Programmierung
TypeScript erweitert JavaScript Classes um Access Modifiers, Abstract Classes und mehr.
Class Basics
Einfache Class
class Person {
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
greet(): string {
return `Hello, I'm ${this.name}`
}
}
const person = new Person("Max", 25)
console.log(person.greet()) // "Hello, I'm Max"
Shorthand Constructor
TypeScript hat eine kürzere Syntax:
// Lange Version
class Person {
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
}
// Kurze Version - identisch!
class Person {
constructor(
public name: string,
public age: number
) {}
}
Das public Keyword erstellt automatisch Properties!
Access Modifiers
TypeScript hat 3 Access Modifiers:
public (Standard)
Von überall zugänglich:
class Person {
public name: string // public ist default
constructor(name: string) {
this.name = name
}
}
const person = new Person("Max")
console.log(person.name) // ✅ OK
private
Nur innerhalb der Class zugänglich:
class Person {
private age: number
constructor(age: number) {
this.age = age
}
getAge(): number {
return this.age // ✅ OK innerhalb der Class
}
}
const person = new Person(25)
console.log(person.age) // ❌ Error: age is private
console.log(person.getAge()) // ✅ OK: 25
protected
Innerhalb der Class UND Subclasses:
class Person {
protected name: string
constructor(name: string) {
this.name = name
}
}
class Employee extends Person {
getEmployeeName(): string {
return this.name // ✅ OK in Subclass
}
}
const person = new Person("Max")
console.log(person.name) // ❌ Error: name is protected
Readonly Properties
Properties die nach Constructor nicht änderbar sind:
class Person {
readonly id: number
name: string
constructor(id: number, name: string) {
this.id = id
this.name = name
}
changeName(newName: string) {
this.name = newName // ✅ OK
this.id = 999 // ❌ Error: readonly
}
}
const person = new Person(1, "Max")
person.name = "Anna" // ✅ OK
person.id = 2 // ❌ Error: readonly
Getters und Setters
Computed Properties mit Validierung:
class Person {
private _age: number = 0
get age(): number {
return this._age
}
set age(value: number) {
if (value < 0 || value > 150) {
throw new Error("Invalid age")
}
this._age = value
}
}
const person = new Person()
person.age = 25 // Nutzt Setter
console.log(person.age) // Nutzt Getter: 25
person.age = -5 // ❌ Error: Invalid age
Best Practice: Private Property mit _ und public Getter/Setter
Static Members
Properties/Methoden auf der Class selbst:
class MathHelper {
static PI: number = 3.14159
static calculateCircleArea(radius: number): number {
return this.PI * radius * radius
}
}
// Ohne Instanz aufrufen
console.log(MathHelper.PI) // 3.14159
console.log(MathHelper.calculateCircleArea(5)) // 78.54
Nutzung:
class Counter {
static count: number = 0
constructor() {
Counter.count++ // Zugriff auf static member
}
static getCount(): number {
return Counter.count
}
}
new Counter()
new Counter()
console.log(Counter.getCount()) // 2
Inheritance (Vererbung)
Classes können von anderen Classes erben:
class Animal {
constructor(public name: string) {}
move(distance: number): void {
console.log(`${this.name} moved ${distance}m`)
}
}
class Dog extends Animal {
bark(): void {
console.log("Woof! Woof!")
}
}
const dog = new Dog("Buddy")
dog.move(10) // "Buddy moved 10m"
dog.bark() // "Woof! Woof!"
super() im Constructor
Subclass muss super() aufrufen:
class Animal {
constructor(public name: string) {}
}
class Dog extends Animal {
constructor(name: string, public breed: string) {
super(name) // ✅ Muss ZUERST aufgerufen werden
this.breed = breed
}
}
const dog = new Dog("Buddy", "Golden Retriever")
Methoden überschreiben
class Animal {
makeSound(): void {
console.log("Some sound")
}
}
class Dog extends Animal {
makeSound(): void {
console.log("Woof!")
}
}
class Cat extends Animal {
makeSound(): void {
console.log("Meow!")
}
}
const animals: Animal[] = [new Dog(), new Cat()]
animals.forEach(animal => animal.makeSound())
// "Woof!"
// "Meow!"
Abstract Classes
Classes die NICHT instanziiert werden können:
abstract class Shape {
abstract getArea(): number // Muss implementiert werden
printArea(): void {
console.log(`Area: ${this.getArea()}`)
}
}
class Circle extends Shape {
constructor(public radius: number) {
super()
}
getArea(): number {
return Math.PI * this.radius ** 2
}
}
class Rectangle extends Shape {
constructor(
public width: number,
public height: number
) {
super()
}
getArea(): number {
return this.width * this.height
}
}
const circle = new Circle(5)
circle.printArea() // "Area: 78.54"
const shape = new Shape() // ❌ Error: Cannot create instance of abstract class
Verwendung:
- Base Classes mit gemeinsamer Logik
- Enforced Methods in Subclasses
- Polymorphismus
Implementing Interfaces
Classes können Interfaces implementieren:
interface Printable {
print(): void
}
interface Saveable {
save(): void
}
class Document implements Printable, Saveable {
constructor(public title: string) {}
print(): void {
console.log(`Printing: ${this.title}`)
}
save(): void {
console.log(`Saving: ${this.title}`)
}
}
const doc = new Document("My Doc")
doc.print()
doc.save()
Interface vs Abstract Class:
| Feature | Interface | Abstract Class | |---------|-----------|----------------| | Implementierung | Nur Signatur | Kann Implementierung haben | | Multiple | ✅ Ja | ❌ Nein (nur single inheritance) | | Constructor | ❌ Nein | ✅ Ja | | Access Modifiers | ❌ Nein | ✅ Ja |
Parameter Properties
Shorthand für Properties im Constructor:
class Person {
constructor(
public name: string,
private age: number,
protected email: string,
readonly id: number
) {}
}
// Identisch zu:
class Person {
public name: string
private age: number
protected email: string
readonly id: number
constructor(name: string, age: number, email: string, id: number) {
this.name = name
this.age = age
this.email = email
this.id = id
}
}
abstract class Employee {
private static nextId: number = 1
readonly id: number
constructor(
public name: string,
protected salary: number
) {
this.id = Employee.nextId++
}
abstract calculateBonus(): number
get monthlySalary(): number {
return this.salary / 12
}
set monthlySalary(value: number) {
this.salary = value * 12
}
displayInfo(): void {
console.log(`${this.name} (ID: ${this.id})`)
}
}
class Developer extends Employee {
constructor(
name: string,
salary: number,
public programmingLanguage: string
) {
super(name, salary)
}
calculateBonus(): number {
return this.salary * 0.15
}
code(): void {
console.log(`Coding in ${this.programmingLanguage}`)
}
}
const dev = new Developer("Max", 60000, "TypeScript")
dev.displayInfo()
console.log(dev.calculateBonus())
dev.code()📝 Quiz
Was ist der Unterschied zwischen private und protected?
Tipps & Tricks
Private Fields mit
ES2022 hat echte Private Fields:
class Person {
#age: number // Echtes Private Field
constructor(age: number) {
this.#age = age
}
getAge() {
return this.#age
}
}
Unterschied zu TypeScript private:
privateist nur Compile-Time#ist Runtime Private
Method Chaining
class Calculator {
private value: number = 0
add(n: number): this {
this.value += n
return this
}
multiply(n: number): this {
this.value *= n
return this
}
getResult(): number {
return this.value
}
}
const result = new Calculator()
.add(5)
.multiply(2)
.add(3)
.getResult() // 13
Generic Classes
class Box<T> {
constructor(private value: T) {}
getValue(): T {
return this.value
}
setValue(value: T): void {
this.value = value
}
}
const numberBox = new Box(42)
const stringBox = new Box("Hello")
Häufige Fehler
Fehler 1: super() vergessen
❌ FALSCH:
class Animal {
constructor(public name: string) {}
}
class Dog extends Animal {
constructor(name: string, breed: string) {
this.breed = breed // ❌ Error: 'super' must be called first
}
}
✅ RICHTIG:
class Dog extends Animal {
constructor(name: string, public breed: string) {
super(name) // ✅ ZUERST super()
this.breed = breed
}
}
Fehler 2: this in Arrow Functions
❌ PROBLEM:
class Button {
text: string = "Click"
handleClick = function() {
console.log(this.text) // this kann undefined sein
}
}
✅ RICHTIG:
class Button {
text: string = "Click"
handleClick = () => {
console.log(this.text) // this ist immer Button
}
}
Fehler 3: Abstract Methoden ohne abstract keyword
❌ FALSCH:
abstract class Shape {
getArea(): number {
return 0 // Dummy Implementierung
}
}
✅ RICHTIG:
abstract class Shape {
abstract getArea(): number // Muss implementiert werden
}
Zusammenfassung
Du hast gelernt:
- ✅ Classes mit Properties und Methoden
- ✅ Access Modifiers: public, private, protected
- ✅ Readonly Properties
- ✅ Getters und Setters
- ✅ Static Members
- ✅ Inheritance mit extends
- ✅ Abstract Classes
- ✅ Interfaces implementieren
Key Takeaways:
- Parameter Properties für kürzeren Code
- Private für Encapsulation
- Abstract Classes für gemeinsame Basis
- Interface für Contracts
- super() muss zuerst aufgerufen werden
Nächste Schritte
Als Nächstes lernst du:
- Generics im Detail
- Advanced Types
- Decorators
- TypeScript mit React
Viel Erfolg! 🚀
Gut gemacht! 🎉
Du hast "TypeScript Classes - Objektorientierte Programmierung" abgeschlossen
Artikel bewerten
Bitte einloggen um zu bewerten
Das könnte dich auch interessieren
TypeScript Interfaces - Objekt-Typen definieren
Lerne wie du mit Interfaces komplexe Objekt-Strukturen typisierst. Optional Properties, Readonly, Extending und mehr.
TypeScript Basic Types - Primitive Datentypen
Lerne die grundlegenden Datentypen in TypeScript kennen: string, number, boolean, arrays, tuples und mehr.
TypeScript Best Practices - Professioneller Code
Lerne die wichtigsten Best Practices für sauberen und wartbaren TypeScript Code. Naming, Patterns, Do's and Don'ts.