In Sproutcore i am using the universal setter/getter method like so:
foo.set('bar', newValue );
val = foo.get('bar');
This is quite different to Objective-c, how would i write a custom getter/ setter?
EDIT
Thanks to those who helped, the way to do it is
bar: function( propKey, propVal ) {
if(propVal===undefined) { // called as getter method
var computedBarValue = ...
return computedBarValue;
} else {
this.bar = propVal + ... // called as setter method
}
}.property()
As you can see, you have one method that is the both the getter and the setter.
if you call
val = foo.get('bar');
the method argument 'propVal' will be undefined.
if you call
foo.set('bar', newValue );
the method argument 'propVal' will be newValue
Custom setter/getter function would look smth like this:
bar: function(key, value){
if(value != undefined){
this._bar = value;
}
return this._bar;
}
This would simply get/set the value. To do smth on set, just add what you want after this._bar = value, to do smth on get, just add if value == undefined.
Related
Can we use more parameters in dart setter method?
Dart setter and getter methods.
Normally we use setter like below
class Student
{
int _age;
void set gettersetter(int a ) => _age=a; //set method
void get gettersetter => _age; //get method
}
void main()
{
var stu = Student();
stu.gettersetter = 2 ;
print(stu.gettersetter);
}
how i can use setter method like below.
void set gettersetter(int a, int b) => _age=a+b;
No.
A setter allows you to have your own code called when you write o.x = 42. It allows you to implement the interface of a (non-final) field without actually having a field, or to intercept the writes to a field. That is all.
If you want a single method to be invoked with two arguments, you'll have to use a plain method void setAgeSum(a, b) { _age = a + b; }.
I have some difficulty to wrap a function that returns a Future.
I have the following code :
class Foo {
Bar data;
}
Future<Foo> getFutureFoo() {...}
I'm would like to create a wrapper that directly returns a Future<Bar>
Future<Bar> getFutureFooBar() {
var foo_future = getFutureFoo();
???
return bar_future;
}
Is there some kind of future transformer like for Streams ?
Future<Bar> getFutureFooBar() async {
Foo foo_future = await getFutureFoo();
//use the foo object to create the Bar object
return bar_future;
}
I'm using Grails with third-party java libraries, and I'd like to override behavior in one of those libraries.
I've attempted to do this in Bootstrap.groovy, like so:
// class overrides
ExpandoMetaClass.enableGlobally()
SimpleStringFilter.metaClass.passesFilter = {Object itemId, Item item ->
final Property<?> p = item.getItemProperty(propertyId);
if (p == null) {
return false;
}
Object propertyValue = p.getValue();
if (propertyValue == null) {
return false;
}
final String value = ignoreCase ? propertyValue.toString()
.toLowerCase() : propertyValue.toString();
if (onlyMatchPrefix) {
if (!value.startsWith(filterString)) {
return false;
}
} else {
if (!value.contains(filterString)) {
return false;
}
}
return true;
}
I know for a fact that the method passesFilter in the SimpleStringFilter class gets called, but I've set a breakpoint in my code above and it's never hit.
For reference, the signature of the java method is:
public boolean passesFilter(Object itemId, Item item)
So, can one actually override behavior in java libraries with ExpandoMetaClass globally? Can someone explain the behavior and nuances of using it in this way?
Thanks!
The issue you are facing is that Java classes don't invoke metaClass. Groovy can't override method calls to Java classes using metaClass.
This is a common misunderstanding when you see something like this:
def object = new MyJavaObject()
object.metaClass.someMethod = { ... }
What is actually happening above is you are creating a Groovy object that wraps the MyJavaObject which then allows that instance to invoke through metaClass.
I want a lazily-initialized property whose initializer I can invoke again if I set the property to nil.
If I define my property this way:
lazy var object = { /*init code*/ }()
...and later invoke the property, the initializer is triggered once. However, if I set object to nil later in my program, the initializer is not invoked again. How can I do that in Swift?
I looked into computed properties but they don't actually store values, so whenever I invoke the variable, the computation or initialization always occurs. I want to compute only whenever the property is nil.
The lazy property initializer is responsible of initializing the property the first time it is accessed in read mode. Setting to nil has no effect on the initialization status - it's just a valid value the property stores.
You can mimic a lazy initialization with 3 properties:
a private initializer, implemented as a computed property (or a closure if you prefer)
a private backing property, storing the actual value
a non private property, which is the one you actually use in your code
The code looks like this:
class MyClass {
private var _myPropInitializer: Int {
return 5
}
private var _myProp: Int?
var myProp: Int? {
get {
if self._myProp == nil {
self._myProp = self._myPropInitializer
}
return _myProp!
}
set {
_myProp = newValue
}
}
}
the initializer property returns a computed value for the variable when it needs to be initialized, which is the 5 integer in the above example
myProp is an optional integer (to be able to store a nil):
on set, it will store the new value in the _myProp property
on get, if _myProp is nil, it invokes the initializer, assigning it to _myProp, and it returns its value
If you want to reuse that pattern, it's better to put everything in a class:
class Lazy<T> {
private let _initializer: () -> T
private var _value: T?
var value: T? {
get {
if self._value == nil {
self._value = self._initializer()
}
return self._value
}
set {
self._value = newValue
}
}
required init(initializer: () -> T) {
self._initializer = initializer
}
}
Note: a struct is not usable because setting a property inside a property getter is not allowed, whereas in a class it is.
Then you can use it as follows:
class MyTestClass {
var lazyProp: Lazy<Int>
init() {
self.lazyProp = Lazy( { return 5 } )
}
}
Some tests in playground:
var x = MyTestClass()
x.lazyProp.value // Prints {Some 5}
x.lazyProp.value = nil
x.lazyProp._value // Prints nil
x.lazyProp.value // Prints {Some 5}
The downside is that you have to access to the actual property as x.lazyProp.value and not as x.lazyProp.
Here's a lazy pattern I use when your object can only ever be nil or a computed value. It requires only 2 properties:
var todayPredicate: NSPredicate! {
set {
guard newValue == nil else {return} // could throw here if required
self._todayPredicateLazyBacker = nil
}
get {
guard self._todayPredicateLazyBacker == nil else {return self. _todayPredicateLazyBacker}
// construct your today predicate
let predicate = ...
self._todayPredicateLazyBacker = predicate
return self._todayPredicateLazyBacker
}
}
private var _todayPredicateLazyBacker: NSPredicate?
todayPredicate is constructed only once when it is read for the first time (lazy).
So why would you ever want to set todayPredicate to nil? In this example you are probably observing for the day changing because todayPredicate must always represent today. In your observer code you would simply do this, for example...
self.todayPredicate = nil
self.loadEvents()
Is there a built-in / easy way to set mappings between domain class properties and JSON strings that don't have exact matches for the property names?
For example, when I have a domain class:
class Person {
String jobTitle
String favoriteColor
static constraints = {
jobTitle(blank: false)
favoriteColor(blank: false)
}
}
And someone's giving me the following JSON:
{ "currentJob" : "secret agent", "the-color" : "red" }
I'd like to be able to still do this:
new Person(request.JSON).save()
Is there a way in groovy/grails for me to map currentJob -> jobTitle and the-color -> favorite color?
EDIT:
I've done a little experimenting, but I still haven't gotten it working. But I have found out a couple interesting things...
At first I tried overwriting the setProperty method:
#Override
setProperty(String name, Object value) {
if(this.hasProperty(name)) this[name] = value
else {
switch(name) {
'currentJob': this.jobTitle = value; break;
'the-color': this.favoriteColor = value; break;
}
}
}
But this doesn't work for two reasons: 1) setProperty is only called if there is a property that matches name and 2) "this[name] = value" calls setProperty, leading to an infinite recursive loop.
So then I thought, well screw it, I know what the incoming json string looks like (If only I could control it), I'll just get rid of the line that handles the scenario where the names match and I'll override hasProperty, maybe that will work:
#Override
void setProperty(String name, Object value) {
switch(name) {
'currentJob': this.jobTitle = value; break;
'the-color': this.favoriteColor = value; break;
}
}
#Override
boolean hasProperty(String name) {
if(name == "currentJob" || name == "the-color") return true
return false
}
But no, that didn't work either. By a random stroke of luck I discovered, that not only did I have to overwrite hasProperty(), but I also had to have an empty setter for the property.
void setCurrentJob(){ }
That hack worked for currentJob - I guess setProperty only gets called if hasProperty returns true and there is a setter for the property (Even if that setter is auto generated under the covers in grails). Unfortunately I can't make a function "setThe-Color" because of the dash, so this solution doesn't work for me.
Still stuck on this, any help would definitely be appreciated.
EDIT:
Overriding the void propertyMissing(String name, Object value){} method is called by this:
Person person = new Person()
person["currentJob"] = "programmer"
person["the-color"] = "red"
But not by this:
Person person = new Person(["currentJob":"programmer", "the-color":"red"])