Reputation: 2356
In OOP I was taught that your objects should only expose their members via getters and should never allow direct mutation.
Looking at some Angular2 apps I always see this concept violated.
export class TodoService {
todos: Array<TodoData> = [];
addTodo(todo: string) {
this.todos.push({
text: todo
});
}
}
In the code above there's no guarantee that a todo won't be added in ways other than the addTodo
method (e.g. calling todoService.todos.push({text: ''})
or even by overwriting the whole todos array).
I always try to eliminate these violation possibilities, which makes my services end up looking similar to this:
export class MyService {
private _myPrimitive: boolean;
get myPrimitive(): { return this._myPrimitive; }
private _myArray: Array<number>;
get myArray(): Array<number> { return this._myArray.splice(0); }
private _myObject: MyObject;
getMyObject(): MyObject { return JSON.parse(JSON.stringify(this._myObject)); }
private _onMyEvent = new Subject<Event>();
get onMyEvent: Observable<Event> { return this._onMyEvent.asObservable(); }
}
I don't see this style of coding in any Angular2 applications. It's not just ugly, it's also slow when it comes to change detection (firing JSON.parse(JSON.stringify(object)
after every 'mousemove' event is very costly) so obviously I'm doing something wrong.
My question is:
Are there more elegant ways to achieve read-only behaivour from outside MyService
.
Why is there no such focus on hiding unnecessary logic in Angular2 than in other OOP languages such as Java/C#/PHP.
Upvotes: 4
Views: 2111
Reputation: 6171
The reason why we have getter/setter for properties is OOP Open/Close principle. For example in Java I have a class Student like below:
class Student {
public:
int age;
}
If I expose the age as a public member like that. Later if there is a request to add a constraint that age should be under 100. I have to search all my program to check for age assignments.
In Typescript you can write like that:
class Student {
age: number
}
Later you can modify only Student class by adding getter or setter.
class Student {
get age() {
}
set age(value: number) {
}
}
And when you use student.age = 15
it will call set age. No need to change outside code. So by default, you don't need to write getter/setter.
For questions to your answers:
You can use public get and private set.
That's opinion is not a fact. You can always set a member under private to hide it from outside.
Upvotes: 1