I'm currently working on CoffeeScript and I got a question that how to write the code below in smart way.
class TestClass
constructor : (name) ->
#name = name if name?
name : "Jack"
sayHi : ->
console.log "Hi #{#name}"
I know constructor : (#name) -> is available to set the argument as instance property though,It doesn't work if I want to use class property instead when the argument is missing.
constructor : (#name) -> declare this.name even if the argument is null
class TestClass
constructor : (#name) ->
name : "Jack"
sayHi : ->
console.log "Hi #{#name}"
foo = new TestClass()
foo.sayHi()
# "hi undefined" because foo.name exists with null value.
Of course I've already tried constructor : (#name?) -> but this would trigger a syntax error.
Is there any better way or I have to write the code #name = name if name? and is the best way so far?
thanks for your help
What about using default value for constructor argument?
class TestClass
constructor: (#name = "Jack") ->
class TestClass
_name = "Jack"
constructor : (#name = _name) ->
tc = new TestClass
console.log tc
tc = new TestClass("Paul")
console.log tc
Producing:
{ name: 'Jack' }
{ name: 'Paul' }
Related
Let's say I have the following interface in F#:
type InterfaceA =
abstract Magic : InterfaceA -> InterfaceA
How can I implement such interface?
When I try to do it like this:
type MyTypeA = {x:int} with
interface InterfaceA with
member self.Magic another =
{x=self.x+another.x}
I get the error:
This expression was expected to have type 'InterfaceA' but here has type 'MyTypeA'
To fix the type error, you need to explicitly cast the returned value to the InterfaceA type - unlike for example C#, F# does not do this automatically:
type InterfaceA =
abstract Magic : InterfaceA -> InterfaceA
abstract Value : int
type MyTypeA =
{x:int}
interface InterfaceA with
member self.Value = self.x
member self.Magic another =
{ x=self.x+another.Value } :> InterfaceA
Note that your code also did not work because another was of type InterfaceA and so it did not have the x field you could access. To fix this, I added a member Value to the interface.
Posting as an alternative that's not really better, just different:
As of F# 6, you can also annotate the return type and the compiler will infer what you mean:
type InterfaceA =
abstract Magic : InterfaceA -> InterfaceA
abstract Value : int
type MyTypeA =
{x:int}
interface InterfaceA with
member self.Value = self.x
member self.Magic another : InterfaceA =
{ x=self.x+another.Value }
I'm trying to make a class with method which modifies it's instance and returning it back.
class OUser {
var name = ""
var car = ""
var city = ""
operator fun get(param: String): String {
return this[param]
}
operator fun set(param: String, value: String) {
this[param] = value
}
fun fromData(data: HashMap<String, String>): OUser {
this::class.declaredMemberProperties.forEach {
this[it.name] = data[it.name]
}
return this
}
}
But this results in infinite loop of calling itself.
The idea was to make possible to work with class in this way:
val data = hashMapOf<String, String>( "name" to "Alex", "car" to "BMW", "city" to "New York" )
val info: OUser = OUser().fromData(data)
val param = "name"
val name = info[param]
info[param] = "Bob"
What is the proper way to make this behaviour possible?
I'll start saying that I don't know why you want such a behavior when you have those properties as public var.
Said that, to make that behaviour possible, the solution is way more complicated than yours, because both the operator fun should access the class properties.
The comments I made will (hopefully) say it all:
class OUser {
var name = ""
var car = ""
var city = ""
// Cache the mutable String properties of this class to access them faster after.
private val properties by lazy {
this::class.declaredMemberProperties
// We only care about mutable String properties.
.filterIsInstance<KMutableProperty1<OUser, String>>()
// Map the property name to the property.
.map { property -> property.name to property }
.toMap()
}
operator fun get(param: String): String = properties.getValue(param).get(this)
operator fun set(param: String, value: String) {
properties.getValue(param).set(this, value)
}
fun fromData(data: HashMap<String, String>): OUser = apply {
data.forEach { (param, value) ->
// Invoke the "operator fun set" on each key-pair.
this[param] = value
}
}
}
If I have a kotlin class like this :
data class Anim (val name : String , var age : Int) {
constructor (a:Anim):this(a.name, a.age) {
}
constructor () :this("Dog") { }
}
and I want Use constructor reference syntax ,
val a = ::Anim
then I got this error :
overload resolution ambiguity:
public constructor PornModel() defined in com.ripple.PornModel
public constructor PornModel(a: PornModel) defined in com.ripple.PornModel
public constructor PornModel(name: String, country: String = ...)
defined in com.ripple.PornModel
val a = ::PornModel::( String, String))
Please tell me how special the arguments
Any help is much appreciated! Al
As stated in the error message Kotlin compiler does not know which constructor overload to pick. You have state the type of a explicitly e.g.:
val twoArgs: (String, Int) -> Anim = ::Anim
val oneArg: (Anim) -> Anim = ::Anim
val noArg: () -> Anim = ::Anim
There are two merge methods in RACSignal:
- (RACSignal *)merge:(RACSignal *)signal;
+ (RACSignal *)merge:(id<NSFastEnumeration>)signals;
When I write RACSignal.merge it references static method:
class func merge(signals: NSFastEnumeration!) -> RACSignal!
How to reference object method? I can't write self.merge, because it is in wrapper class and self is not RACSignal.
The curried class function and the curried instance function have
different signatures. Similarly as in
Swift - get reference to a function with same name but different parameters
you can refer to each by specifying the signature explicitly.
I have no experience with RACSignal, so here is an artificial
example that hopefully can be applied in your case:
class MyClass {
class func foo(s : String) {
println("class foo: \(s)")
}
func foo(s : String) {
println("instance foo: \(s)")
}
}
// Reference to the class method:
let f1 : String -> Void = MyClass.foo
// Call the class method:
f1("bar")
// Output: class foo: bar
// Reference to the instance method:
let f2 : MyClass -> String -> Void = MyClass.foo
// Call the instance method:
let obj = MyClass()
f2(obj)("bar")
// Output: instance foo: bar
As methods in Swift are curried class functions, compiler has to decide which overload to choose.
To reference instance's merge method you need to specify it's exact type:
let instanceMerge: RACSignal -> RACSignal! -> RACSignal! = RACSignal.merge
Say I have a Coffeescript class like this:
class Foo
aVar = 'foo'
someFunction = ->
anotherVar = 'bar'
Is there a way to set anotherVar as a class variable without having to declare it as null, like so:
class Foo
aVar = 'foo'
anotherVar = null
someFunction = ->
anotherVar = 'bar'
No, you can't. Let us look at a simple class:
class C
cv = null
m: -> cv
That is converted to this JavaScript:
var C = (function() {
var cv;
function C() {}
cv = null;
C.prototype.m = function() {
return cv;
};
return C;
})();
You'll notice that the "private class variable" cv is just a local variable inside the self-executing function that builds C. So, if we wanted to add a new "private class variable" to C, we'd have to open that anonymous function's scope again and add new variables. But there's no way to travel back in time and alter the scope of a function that has already executed so you're out of luck.
You don't have to define your anotherVar as null when you define it but you have to initialize it to something.
Have you ever heard about this keyword? :) CoffeeScript maps # into this:
class Foo
aVar = 'foo'
someFunction: ->
#anotherVar = 'bar'