Skip to content

Commit

Permalink
Fixed inconsistency in exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
dirkriehle committed Nov 20, 2024
1 parent d9138b3 commit 15d5493
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 59 deletions.
52 changes: 0 additions & 52 deletions src/adap-b03/variance/Panels.ts

This file was deleted.

98 changes: 98 additions & 0 deletions src/adap-b03/variance/Views.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { User, Moderator, Administrator } from "./Users";

class UserView {

protected user: User = new User();

constructor(user?: User) {
if(user != undefined) this.user = user;
}

public getUser(): User {
return this.user;
}

public setUser(user: User): void {
this.user = user;
}

}

class ModeratorView extends UserView {

constructor(mod?: Moderator) {
super(mod);
}

// Covariant redefinition of return type is allowed
public getUser(): Moderator {
return this.user as Moderator;
}

// Covariant redefinition of argument type (why is this allowed?)
public setUser(user: Moderator): void {
this.user = user;
}

}

/**
* Example for covariant redefinition of return type
*/
let modView1: ModeratorView = new ModeratorView(new Moderator());
let modAsUserView1: UserView = modView1 as UserView;
let mod1: Moderator = modAsUserView1.getUser() as Moderator;
mod1.moderate(); // should work, no problem

/**
* Example for covariant redefinition of argument type
*/
let modView2: ModeratorView = new ModeratorView(new Moderator());
let modAsUserView2 = modView2 as UserView;
modAsUserView2.setUser(new User()); // sets up for failure
let mod2: Moderator = modView2.getUser(); // creates failure point
mod2.moderate(); // should fail because mod2 is of dyanmic type User

class AdministratorView extends ModeratorView {

constructor(admin?: Administrator) {
super(admin);
}

// @ts-expect-error Contravariant redefinition of return type not allowed
public getUser(): User {
return this.user;
}

// Contravariant redefinition of argument type is allowed
public setUser(user: User): void {
this.user = user;
}

}

/**
* Example for contravariant redefinition of return type
*/
let adminView: AdministratorView = new AdministratorView();
let adminViewAsModView1: ModeratorView = adminView as ModeratorView;
let mod3: Moderator = adminViewAsModView1.getUser();
mod3.moderate() // will fail because mod3 is of dynamic type User

/**
* Example 1 for contravariant redefinition of argument type
*/
adminView.setUser(new User());
let user1: User = adminView.getUser();
user1.use(); // no problem
let admin1: Administrator = user1 as Administrator;
admin1.administer(); // will fail but also was not promised

/**
* Example 2 for contravariant redefinition of argument type
*/
adminView.setUser(new Administrator());
let user2: User = adminView.getUser();
user2.use(); // still no problem
let admin2: Administrator = user2 as Administrator;
admin2.administer(); // will work but only because of extra knowledge
4 changes: 1 addition & 3 deletions src/adap-b04/common/IllegalArgumentException.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ export class IllegalArgumentException extends Exception {
}

static assertCondition(cond: boolean, exMsg: string): void {
if (!cond) {
throw new IllegalArgumentException(exMsg);
}
if (!cond) throw new IllegalArgumentException(exMsg);
}

constructor(m: string) {
Expand Down
4 changes: 2 additions & 2 deletions src/adap-b04/common/InvalidStateException.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { Exception } from "./Exception";
*/
export class InvalidStateException extends Exception {

static assertNotNullOrUndefined(o: Object | null, exMsg: string = "null or undefined"): void {
this.assertCondition(this.isNullOrUndefined(o), exMsg);
static assertIsNotNullOrUndefined(o: Object | null, exMsg: string = "null or undefined"): void {
this.assertCondition(!this.isNullOrUndefined(o), exMsg);
}

static assertCondition(cond: boolean, exMsg: string): void {
Expand Down
4 changes: 2 additions & 2 deletions src/adap-b04/common/MethodFailureException.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { Exception } from "./Exception";
*/
export class MethodFailureException extends Exception {

static assertNotNullOrUndefined(o: Object | null, exMsg: string = "null or undefined"): void {
this.assertCondition(this.isNullOrUndefined(o), exMsg);
static assertIsNotNullOrUndefined(o: Object | null, exMsg: string = "null or undefined"): void {
this.assertCondition(!this.isNullOrUndefined(o), exMsg);
}

static assertCondition(cond: boolean, exMsg: string): void {
Expand Down
20 changes: 20 additions & 0 deletions test/adap-b04/common/Exceptions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { describe, it, expect } from "vitest";

import { IllegalArgumentException } from "../../../src/adap-b04/common/IllegalArgumentException";
import { MethodFailureException } from "../../../src/adap-b04/common/MethodFailureException";
import { InvalidStateException } from "../../../src/adap-b04/common/InvalidStateException";

describe("Asserting not null or undefined", () => {
it("test asserIsNotNullOrUndefined", async () => {
const exMsg: string = "null or undefined";

IllegalArgumentException.assertIsNotNullOrUndefined("hurray!");
expect(() => IllegalArgumentException.assertIsNotNullOrUndefined(null)).toThrow(new IllegalArgumentException(exMsg));

MethodFailureException.assertIsNotNullOrUndefined("hurray!");
expect(() => MethodFailureException.assertIsNotNullOrUndefined(null)).toThrow(new MethodFailureException(exMsg));

InvalidStateException.assertIsNotNullOrUndefined("hurray!");
expect(() => InvalidStateException.assertIsNotNullOrUndefined(null)).toThrow(new InvalidStateException(exMsg));
});
});

0 comments on commit 15d5493

Please sign in to comment.