There’s two notions at play here, one is object-oriented programming (which
javascript handles quite well), the other is a static typing system (which
javascript being a dynamic language doesn’t natively support).
It’s important to understand that you can do object-oriented programming
without static typing, classes, explicit interfaces, or inheritance.
Similarly, just because you are using classes, interfaces, or inheritance
doesn’t mean your code is object-oriented.
I understand why you are troubled by the notion that you shouldn’t just be
able to trust an object implements the correct interface simply because it
has methods with the right names. Technically speaking, you are absolutely
correct. The push method of an object I pass in might very well just do a
window.alert('I'm
not pushing').
However, what you have to realize is that there is always an implicit
contract between methods and API’s you write, and the people who use those
API’s. When you write a function, you have to document or show examples of
what it does, what parameters it expects and what it will return. A
statically typed language provides some tools to help document and enforce
*some* of that contract at compile time. However, static typing can only go
so far to enforce a contract, so you still have to trust the caller. For
example, even with static typing I can create a group and have it implement
a “List” interface but there is nothing preventing me from implementing the
list interface incorrectly, or even purposefully not behaving as a faithful
implementation of a list contract (i.e. I can still “push” persons off a
cliff rather than add them to my group).
Duck-typing can be a useful tool in dynamically typed languages, as long as
your contracts is documented. For example, in your method you would say:
“if the first parameter proviides a push method it will be interpreted as
an array-like object and the method used to add items to it”. While this
contract is not enforced by the language itself or the compiler, it is
still a contract nonetheless. If the user of your method chooses to pass in
an object with a push that does something other than what the contract
requires, they should not expect it to work correctly.
We use these kind of contracts all the time in angular and don’t think much
of them. Take for example controller definitions, they take a string and a
constructor, but the constructor could be a function, or it could be an
array where where each element is a string and the last element is a
function (for dependency injection). So the following two are valid ways of
defining a controller:
app.controller('myController', function($scope){
});
app.controller('myController', ['$scope', function($scope){
}]);
This is a contract we are all familiar with, but it’s not enforced by the
language, I could pass an array of integers as the second parameters but it
would not really work because I’m violating the contract in the
documentation. I could pass a list of strings that don’t actually match any
services in my module and angular would throw me an exception because the
contract states that these strings should be the names of valid services.
My point is that the contract is between a method and those who use the
method. Static typing can only help partially document and enforce some
aspects of the contract, but often not the entire contract, so there will
always be a level of trust that the objects passed in to your function
behave as specified in the contract (even when using static typing).
--
You received this message because you are subscribed to the Google Groups
"AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/groups/opt_out.