CoffeeScript: Using instanceof vs Class.constructor.name - coffeescript

If I have a class:
class Haha
constructor: (#lolAmount = 1) ->
alert #lolAmount
And I want to check if an object is of the right class, Is it always safe to use constructor.name:
haha = new Haha()
unless haha.constructor.name is 'Haha'
throw Error 'Wrong type'
or is it better to use instanceof:
haha = new Haha()
unless haha instanceof Haha
throw Error 'Wrong type'
One argument I have for instanceof is when using extends:
class BigHaha extends Haha
bigHaha = new BigHaha
console.log bigHaha instanceof Haha #true
but how safe is it, being a JavaScript operator - I feel like I should be sceptical about it.
On the other hand, with constructor.name it is very clear what is happening. Is it guaranteed that constructor.name will be set on all objects?
Thanks for any info.

First of all, constructor is also straight JavaScript:
Returns a reference to the Object function that created the instance's prototype.
So when you say o.constructor, you're really doing straight JavaScript, the name constructor for the CoffeeScript object initialization function is a separate matter.
So now you have a choice between using JavaScript's constructor property or JavaScript's instanceof operator. The constructor just tells you what "class" was used to create the object, instanceof on the other hand:
[...] tests whether an object has in its prototype chain the prototype property of a constructor.
So instanceof is the right choice if you want to allow for subclassing.

Related

Supporting "recursive objects" in lua

I'm fairly new to lua and have the following problem with an assignment from a class:
We currently extend lua to support objects and inheritance. The Syntax for that is
Class{'MyClass',
attribute1 = String,
attribute2 = Number
}
Class{'MySubClass', MyClass,
attribute3 = Number
}
This works perfectly fine. The real problem lies within the next task: We should support "recursive types", that means a call like
Class{'MyClass', attribute = MyClass}
should result in an class with a field of the same type as the class. When this "class-constructor" is called the variable MyClass is nil, thats why the parameter table doesnt't have an entry attribute. How is it possible to access this attribute?
My first thought was using some kind of nil-table which gets returned every time the global __index is called with an unset key. This nil-table should behave like the normal nil, but can be checked for in the "class-constructor". The problem with this approach are comparisons like nil == unknown. This should return true, but as the __eq meta method of the nil-table is never called we cannot return true.
Is there another approach I'm currently just ignoring? Any hint is greatly appreciated.
Thanks in advance.
Edit:
Here the relevant part of the "testfile". The test by which the code is rated in class is another one and gets published later.
three = 3
print( three == 3 , "Should be true")
print( unknown == nil , "Should be true" )
Class{'AClass', name = String, ref = AClass}
function AClass:write()
print("AClass:write(), name of AClass:", self.name)
end
aclass = AClass:create("A. Class")
aclass:write()
Since MyClass is just a lookup in the global table (_G), you could mess with its metatable's __index to return a newly-defined MyClass object (which you would later need to fill with the details).
However, while feasible, such an implementation is
wildly unsafe, as you could end up with an undefined class (or worse, you may end up inadvertantly creating an infinite lookup loop. Trust me, I've been there)
very hard to debug, as every _G lookup for a non-existing variable will now return a newly created class object instead of nil (this problem could somewhat be reduced by requiring that class names start with an uppercase character)
If you go that route, be sure to also override __newindex.
How about providing the argument in string form?
Class{'MyClass', attribute = 'MyClass'}
Detect strings inside the implementation of Class and process them with _G[string] after creating the class
Or alternatively, use a function to delay the lookup:
Class{'MyClass', attribute = function() return MyClass end}

How do I cast to an interface an object may implement?

I have the following classes & interfaces:
export interface IBody {
body : ListBody;
}
export class Element {
// ...
}
export class Paragraph extends Element implements IBody {
// ...
}
export class Character extends Element {
// ...
}
I have code where I will get an array of Element derived objects (there are more than just Paragraph & Character). In the case of those that implement IBody, I need to take action on the elements in the body.
What is the best way to see if it implements IBody? Is it "if (element.body !== undefined)"?
And then how do I access it? "var bodyElement = <IBody> element;" gives me an error.
C:/src/jenova/Dev/Merge/AutoTagWeb/client/layout/document/elements/factory.ts(34,27): error TS2012: Cannot convert 'Element' to 'IBody':
Type 'Element' is missing property 'body' from type 'IBody'.
Type 'IBody' is missing property 'type' from type 'Element'.
thanks - dave
An interface in TypeScript is a compile-time only construct, with no run-time representation. You might find section 7 of the TypeScript specification interesting to read as it has the complete details.
So, you can't "test" for an interface specifically. Done correctly and completely, you generally shouldn't need to test for it as the compiler should have caught the cases where an object didn't implement the necessary interface. If you were to try using a type assertion:
// // where e has been typed as any, not an Element
var body = <IBody> e;
The compiler will allow it without warning as you've asserted that the type is an IBody. If however, e were an Element in scope, the compiler as you've shown will check the signature of the Element and confirm that it has the properties/methods declared by IBody. It's important to note that it's checking the signature -- it doesn't matter that it may not implement IBody as long as the signature matches up.
Assuming that Element has a signature that matches IBody, it will work. If it does not, you'll get the compiler error you're receiving. But, again, if it's declared as any, the assertion will pass and at run-time, unless the type has the methods defined on IBody, the script will fail.
As your Element is the base class, you cannot check for IBody. You could declare an argument as any:
function someFeature(e: any) {
}
And then assert that the IBody is present:
function someFeature(e: any) {
var body :IBody = <IBody> e;
// do something
}
However, if you do need a run-time check, you'd need to look for the function on the prototype or as a property before using it. While that could be misleading in some cases, the interface in TypeScript also may not have caught the mismatch either. Here's an example of how you could check for the existence of a specific function.
It might look like this:
function someFeature(e: any) {
var body = <IBody> e;
if (typeof (body.someFunctionOnBodyInterface) === "undefined") {
// not safe to use the function
throw new Error("Yikes!");
}
body.someFunctionOnBodyInterface();
}

Subclassing native objects: instanceof not working properly

I'm trying to subclass the native JS Error object in CoffeeScript to get specialized error types, but i found that the instanceof does not work correctly if i don't define a constructor in the subclasses:
class SimpleError extends Error
class EmptyConstructorError extends Error
constructor: ->
class SuperConstructorError extends Error
constructor: ->
super
new SimpleError instanceof SimpleError # -> false
new EmptyConstructorError instanceof EmptyConstructorError # -> true
new SuperConstructorError instanceof SuperConstructorError # -> true
The problem seems to be caused by how the generated JS constructor functions are defined. When i don't define a constructor in CoffeeScript:
SimpleError = (function(_super) {
__extends(SimpleError, _super);
function SimpleError() {
return SimpleError.__super__.constructor.apply(this, arguments);
}
return SimpleError;
})(Error);
And when i do define a constructor in CoffeeScript:
SuperConstructorError = (function(_super) {
__extends(SuperConstructorError, _super);
function SuperConstructorError() {
SuperConstructorError.__super__.constructor.apply(this, arguments);
}
return SuperConstructorError;
})(Error);
As you can see, the difference is a simple return in the first case. I don't understand why this makes any difference in the instanceof behavior though, as the super constructor is just being applied to the this object (i.e. the super constructor is not being called with new), but then again i don't understand a whole lot of how JS constructors work =P
And the weird thing is that this behavior seems to only happen when subclassing native JS objects. If i subclass CoffeeScript classes everything works as expected.
Any idea of why this might be happening and how could i avoid writing dummy constructors just for the instanceof operator to work correctly?
Thanks!
Update
So the user matyr answered with a link to the commit where this behavior was introduced, but it doesn't quite explain what is happening here, so i'll try to explain that a little bit in case anyone else wonders why this works this way.
The main problem is this inherited nasty "feature" from JavaScript which let us define a constructor function that returns an object other than the one being constructed:
function Foo() {
return {'LOL': 'You fool!'};
}
new Foo() instanceof Foo // -> false
And there is also the fact that some native constructors, like Error, Array, String and whatnot don't need to be called with new: they will just return a new object of the corresponding type if you happen to forget it.
In the end, add these two ugly things together and the result is that you should remember to write class MyError extends Error then constructor: -> super instead of the more intuitive class MyError extends Error if you want the instanceof operator to work properly with MyError. That's because CoffeeScript's implicit constructor will just return whatever the parent constructor returns, and in this case will do return Error.apply(this, arguments) which will just return a shinny new error object instead of the object you passed as the this argument. Yay!
Update 2 (Feb 25 2013)
This problem was fixed in CoffeeScript 1.5.0! =D
Now extending native objects works as expected:
class MyError extends Error
new MyError instanceof MyError # -> true :)
Update 3 (Mar 04 2013)
Aaand it's gone on 1.6.0 =P
For better or worse, the return was added on 1.3.1 to fix #1966 (and #2111).

Why must my coffeescript method belong to the class?

I come from a C#/Java background which use a class based OO system and I don't get the JavaScript/CoffeeScript prototype OO system yet. I've written a CoffeeScript class below which allows me to display names for contacts according to a system-side preference. I can only get the class to work by making the joinNonEmpty(stringList, joinText) method belong to the prototype and calling it the way I would call a static method in Java/C# land.
Is there a way I can make this method call using this.joinNonEmpty(...)?
Can you shed some light on why I can reference the firstLastRender, lastFirstRender and firstOrNickThenLast methods in the constructor with this. but it doesn't work from those methods when calling the joinNonEmpty helper?
Does this have something to do with how I'm locating the appropriate method via the preference map?
prefs = displayNameFormat: "FirstOrNickThenLast"
class DisplayNameRenderer
constructor: ->
#prefToRenderMap =
FirstLast: this.firstLastRender
LastFirst: this.lastFirstRender
FirstOrNickThenLast: this.firstOrNickThenLast
# Why does this method have to be static (a class method)?
#joinNonEmpty: (stringList, joinText) ->
nonEmptyStrings = []
for s in stringList
nonEmptyStrings.push(s) if s isnt null and s isnt ""
nonEmptyStrings.join(joinText)
firstLastRender: (contact) ->
# TypeError: Object expected.
joinNonEmpty([contact.firstName, contact.lastName], ' ')
lastFirstRender: (contact) ->
# TypeError: Object doesn't support this method or property
this.joinNonEmpty([contact.lastName, contact.firstName], ', ')
firstOrNickThenLast: (contact) ->
# Works correctly.
DisplayNameRenderer.joinNonEmpty([(if contact.nickname isnt null and contact.nickname isnt "" then contact.nickname else contact.firstName), contact.lastName], ' ')
render: (contact) ->
#prefToRenderMap[prefs.displayNameFormat](contact)
contact = firstName: "Jonathan", nickname: "Jonny", lastName: "Appleseed"
dnr = new DisplayNameRenderer()
# => "Jonny Appleseed"
console.log dnr.render(contact)
Thanks for taking the time to answer.
this (AKA #) is determined when the function is called (with exceptions as below). So when you do this:
#prefToRenderMap =
FirstLast: this.firstLastRender
LastFirst: this.lastFirstRender
FirstOrNickThenLast: this.firstOrNickThenLast
You're storing unbound references to the three functions in the #prefToRenderMap instance variable and #prefToRenderMap is itself an object. Then you try to call the methods in your DisplayNameRenderer instance like this:
#prefToRenderMap[prefs.displayNameFormat](contact)
and everything falls apart because the methods are called in the wrong context and # isn't what they're expecting it to be. If prefs is 'FirstOrNickThenLast' then you're effectively doing this:
#prefToRenderMap.FirstOrNickThenLast(contact)
and # (AKA this) will be #prefToRenderMap inside the firstOrNickThenLast method. But, of course, #prefToRenderMap doesn't have any of the methods that you're trying to call so you get various errors.
One solution is to use the fat arrow (=>) to define the methods:
The fat arrow => can be used to both define a function, and to bind it to the current value of this, right on the spot.
So you could have things like this:
joinNonEmpty: (stringList, joinText) ->
#...
firstLastRender: (contact) =>
#joinNonEmpty([contact.firstName, contact.lastName], ' ')
and everything will work out. Here's a stripped down demo that will also show you your this problem:
http://jsfiddle.net/ambiguous/RAPJw/1/
You could also avoid this problem by referring to the methods by their names. Given a method name in a string, m = 'some_method', you can call that method like this o[m]() in both JavaScript and CoffeeScript and the result will be the same as if you said o.some_method(). A better structure would look more like this:
class DisplayNameRenderer
constructor: ->
#prefToRenderMap =
FirstOrNickThenLast: 'firstOrNickThenLast'
joinNonEmpty: (stringList, joinText) ->
#...
firstOrNickThenLast: (contact) ->
#joinNonEmpty([(if contact.nickname isnt null and contact.nickname isnt "" then contact.nickname else contact.firstName), contact.lastName], ' ')
render: (contact) ->
#[#prefToRenderMap['FirstOrNickThenLast']](contact)
Note the change to the structure of #prefToRenderMap and how it is used in render. And a demo of this approach: http://jsfiddle.net/ambiguous/DFYwu/
As an aside, instead of saying ClassName.class_method() inside an instance method, you can use the constructor property instead: #constructor.class_method(). Also, you usually say #method() or #property rather than this.method() and this.property in CoffeeScript.

How do I mock a Where clause in EF4

I am re-writing this question to make it clearer what I need to do. I am trying to use Rhino-Mock to test:
public IQueryable<TxRxMode> GetAllModes()
{
return m_context.TxRxModes.Where(txRxMode => txRxMode.Active);
}
Here's the code:
var context = MockRepository.GenerateStub<IProjectContext>();
//Returns an empty list
context.Expect(c => c.TxRxModes.Where(Arg<Func<TxRxMode, bool>>.Is.Anything)).Return(new List<TxRxMode>().AsQueryable());
TxRxModes in an IObjectSet property on the context and I want it to return an empty IQueryable<TxRxMode> object when the return m_context.TxRxModes.Where(txRxMode => txRxMode.Active); code is called.
When I run this, the Expect method call throws the an ArgumentNullException:
Value cannot be null.
Parameter name: predicate
I have tried the simpler:
IObjectSet<TxRxMode> modes = MockRepository.GenerateStub<IObjectSet<TxRxMode>>();
context.Expect(c => c.TxRxModes).Return(modes);
but this throws a null reference exception when I call
return m_context.TxRxModes.Where(txRxMode => txRxMode.Active);
Basically, this is part of the method I am trying to mock, so the key question is how do I mock this Where statement?
Where is actually a global static method and you shouldn't be mocking it. It operates on an IEnumerable however and you could just mock that.
Its kind of a hassle doing it with rhino mocks however. I would recommend doing the mock manually (if you need to do it at all).