Last Sync: 2022-09-20 14:30:05
This commit is contained in:
parent
27e23cdd56
commit
7aa8a034c7
1 changed files with 88 additions and 0 deletions
|
@ -120,4 +120,92 @@ class Programmer implements Person {
|
|||
|
||||
## Inheritance
|
||||
|
||||
We can extend classes in TypeScript by using sub-classes or abstract classes.
|
||||
|
||||
### Sub-classes
|
||||
|
||||
In the case of sub-classes, we use the phrase `[child_class] extends [parent_class]` in the class declaration to designate the inheritance relationship between the base class and the new class that is derived from it.
|
||||
|
||||
> A derived class has all the properies and methods of its base class but can also define additional members.
|
||||
|
||||
When you instantiate a child class from a parent class, if the parent class has constructor values, you must initialise these in the child. You do this by calling the parent constructor via the `super()` syntax. For example:
|
||||
|
||||
```ts
|
||||
class Employee extends Person {
|
||||
constructor(firstName: string, lastName: string, private jobTitle: string) {
|
||||
// call the constructor of the Person class:
|
||||
super(firstName, lastName);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To override or alter a method that exists on the parent in the child, you can use the syntax `super.[methodName]()`.
|
||||
|
||||
### Abstract classes
|
||||
|
||||
Classes marked `abstract` are similar to parent in the case of sub-classes. The difference is that they are like templates. Several of their methods and properties may be directly inherited by classes that derive from them (just like sub-classes) but they can include 'blank' methods and properties that are placeholders for methods and properties that are defined in the derivation class.
|
||||
|
||||
I have found this useful for cases where you want to inherit methods from a parent class but implement a specific method differently in each derivation.
|
||||
|
||||
```ts
|
||||
export abstract class IndexHyperlinksProvider
|
||||
implements vscode.TreeDataProvider<TreeItem>
|
||||
{
|
||||
public activeFile: string | undefined
|
||||
private outlinks
|
||||
private fileSystemUtils: FileSystemUtils
|
||||
|
||||
constructor(
|
||||
activeFile: string | undefined,
|
||||
workspaceRoot: string | undefined
|
||||
) {
|
||||
this.setActiveFile(activeFile)
|
||||
this.outlinks = this.generateLinks()
|
||||
this.fileSystemUtils = new FileSystemUtils(workspaceRoot)
|
||||
}
|
||||
|
||||
abstract generateLinks(): Promise<TreeItem[] | undefined>
|
||||
|
||||
public setActiveFile(activeFile: string | undefined) {
|
||||
this.activeFile = activeFile
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
Above we have a base class with a single abstract method `generateLinks()`. The class below extends this base. Note that it passes the parent constructor values to `super` and defines an actual method for the designated `generateLinks()` template:
|
||||
|
||||
```ts
|
||||
export class IndexOutlinksProvider extends IndexHyperlinksProvider {
|
||||
public workspaceFiles: string[];
|
||||
public context: vscode.ExtensionContext;
|
||||
constructor(
|
||||
activeFile: string | undefined,
|
||||
workspaceRoot: string | undefined,
|
||||
workspaceFiles: string[],
|
||||
context: vscode.ExtensionContext
|
||||
) {
|
||||
super(activeFile, workspaceRoot);
|
||||
this.workspaceFiles = workspaceFiles;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public async generateLinks(): Promise<TreeItem[] | undefined> {
|
||||
const indexer = new IndexHyperlinks(this.context, this.workspaceFiles);
|
||||
if (typeof this.activeFile === "string") {
|
||||
const outlinks = await indexer.indexOutlinks(this.activeFile);
|
||||
if (outlinks !== undefined) {
|
||||
return this.transformLinksToTreeItem(outlinks);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> Importantly, you cannot instantiate abstract classes. You can only `extend` them and then instantiate their derivation. This is another important difference from sub-classes.
|
||||
|
||||
As with sub-classes, you must initialise the properties of the parent constructor with `super`.
|
||||
|
||||
### `implements` vs `extends`
|
||||
|
||||
You shouldn't confuse `implements` with `extends`. `implements` just checks the class as an interface in accordance with the principles of [duck typing](/Programming_Languages/TypeScript/Custom_types.md#duck-typing): i.e the implementing class should have the same properties and methods. It doesn't affect anything internal to the methods or properties. So e.g, if you typed a method parameter as `string` in the base class, this would still default to `any` in the derived class.
|
||||
|
|
Loading…
Add table
Reference in a new issue