Does swift not have nested classes??
For example, I can't seem to access the property test of the master class from the nested class.
class master{
var test = 2;
class nested{
init(){
let example = test; //this doesn't work
}
}
}
Swift's nested classes are not like Java's nested classes. Well, they're like one kind of Java's nested classes, but not the kind you're thinking of.
In Java, an instance of an inner class automatically has a reference to an instance of the outer class (unless the inner class is declared static). You can only create an instance of the inner class if you have an instance of the outer class. That's why in Java you say something like this.new nested().
In Swift, an instance of an inner class is independent of any instance of the outer class. It is as if all inner classes in Swift are declared using Java's static. If you want the instance of the inner class to have a reference to an instance of the outer class, you must make it explicit:
class Master {
var test = 2;
class Nested{
init(master: Master) {
let example = master.test;
}
}
func f() {
// Nested is in scope in the body of Master, so this works:
let n = Nested(master: self)
}
}
var m = Master()
// Outside Master, you must qualify the name of the inner class:
var n = Master.Nested(master:m)
// This doesn't work because Nested isn't an instance property or function:
var n2 = m.Nested()
// This doesn't work because Nested isn't in scope here:
var n3 = Nested(master: m)
This solution is sort of similar to how I use it in C#, and I have successfully tested it in Xcode.
Here's a breakdown of the process:
Your nested class needs to be made optional so you don't have to initialize it, so theres a '?' in the declaration; if you initialize both your parent class and your nested class, you end up with a 'recursion' effect and an error is generated
Create a regular function that receives an argument of the same type as your main class
Pass that argument to your nested class (this can go into the nested object's normal initializer). - Since objects are passed by reference by default, there's nothing special to get your nested class to link to the parent class
Inside your nested class, you need a variable of the same type as your parent class
From here on out set up everything as you normally would.
In the code execution area, your nested class object also needs to be regarded as optional (hence the '?'). If you forget about it, Xcode will add it anyways.
In this example, I wanted to design a keyword "set," so when I set variables, I can type:
testClass.set.(and then a descriptive method name)
Here is the code, and its goal is to output "test" in the console, after the value is set via the nested object:
class testClass
{
var test_string:String = ""
var set: class_set?
func construct_objects(argument: testClass)
{
self.set = class_set(argument: argument)
}
class class_set
{
var parent:testClass
init(argument: testClass)
{
parent = argument
}
func test_string_to_argument(argument: String)
{
parent.test_string = argument
}
}
}
var oTestClass = testClass()
oTestClass.construct_objects(oTestClass)
oTestClass.set?.test_string_to_argument("test")
print(oTestClass.test_string)
Nested for Swift and Java
Swift has Nested Types definitions
Java has more complex hierarchy of nested class
Swift's Nested is more similar to Java's Static Nested, as a result you do not have an access to properties of outer class. To get access of outer class you can pass it as a parameter.
Related
In JavaScript you can do the following:
var obj = {
property: 1,
method1: function() {
//...
},
method2: function() {
//...
}
};
obj.method1()
I am wondering if there is a groovy equivalent for this (a map containing a method). I know this is just like a class, but I dont want a class ha..
Yes, you can put closures inside a map. But this is not the way to get
objects in Groovy. There is no concept of "this", that knows about the
map.
def obj = [
inc: { it + 1 }
]
println obj.inc(10)
Ok so Javascript is not OOP. They have OBJECTS but that is it. What you are showing is an OBJECT.
In Groovy, you can do this with a class that can instantiate the object and then you can do that on the object. For example you can create a CommandObject (which is what you are probably wanting) and then fill in the properties like you want or fill them in on instantiation. For example (using above example):
def paramsDesc = new ParamsDescriptor()
paramsDesc.paramType = 'paramtype'
paramsDesc.keyType = 'keyType'
paramsDesc.name = 'name'
paramsDesc.idReferences = 'id'
paramsDesc.description = 'desc'
paramsDesc.mockData = 'mock'
paramsDesc.values = []
OR (if you create a constructor) you can instantiate all at once:
def paramsDesc = new ParamsDescriptor('paramtype','keyType','name','id','desc','mock',[])
CommandObjects can have methods and functions (like above). But you just have to instantiate them first (def paramsDesc = new ParamsDescriptor())
This is the difference between a class and an object; think of a class as the blueprint and the object as what is created from the blueprint.
I have a Realm Object called Person which contains a reference to a List, where Dog is another Realm Object.
In order to traverse this list of dogs, I store an iterator using the following code (iterator and currentDog are defined within the ViewController)
iterator = selectedPerson.dogs.makeIterator() // dogs: List<Dog>
currentDog = iterator.next()
This performs works as necessary.
However, when trying to update currentDog from another function using the following code, I end up with an exception thrown by the RLMIterator class: EXC_BAD_ACCESS.
if currentDogNumber < selectedPerson.dogs.count {
currentDog = iterator.next()
}
UPDATE:
I no longer receive any errors if I change the second code snippet to the following rather crude code snippet:
if currentDogNumber < selectedPerson.dogs.count {
iterator = selectedPerson.dogs.makeIterator()
for _ in 0...currentDogNumber {
currentDog = interval.next()
}
}
Could this be due to the methods being executed on separate threads?
And if so, how do I ensure that they are executed by the same thread
I'm trying to parse a JSON data and assign it to a POJO in Grails.
I started with
obj.param=jsonRequest.jsonWrap.attrib.something.jsonParam
After some experimenting and refactoring, it looks like this now.
jsonRequest.jsonWrap.attrib.something.with {
obj.param1=jsonParam1
obj.param2=jsonParam2
//...
}
}
Now, can I avoid the repeated use of obj reference?
I'm imagining that your actual starting point is something like the following. On the JSON side:
import groovy.json.JsonSlurper
String jsonText = '''{
"jsonWrap":{
"attrib":{
"something":{
"jsonParam1": "value1",
"jsonParam2": "value2",
"jsonParam3": "value3",
"jsonParam4": "value4",
"jsonParam5": "value5"
}
}
}
}'''
def jsonRequest = new JsonSlurper().parseText(jsonText)
On the Groovy side:
class ObjectType {
def param1, param2, param3, param4, param5
}
def obj = new ObjectType()
Now, if I had any control over how either the JSON side or the Groovy side are defined then I would do my darnedest to ensure that the property names of the JSON "something" object are exactly the same as the property names in the Groovy "ObjectType" class. For example, like this:
class ObjectType {
def jsonParam1, jsonParam2, jsonParam3, jsonParam4, jsonParam5
}
Then, unmarshalling the "something" object into Groovy is as simple as this:
def obj = new ObjectType(jsonRequest.jsonWrap.attrib.something)
Only one reference to the JSON object. Only one reference to the Groovy object. And the former is used to instantiate the latter. And furthermore, notice that there is no need to reference the properties at all. That is, JSON objects from the slurper are instances of Map, so if the property names match up, you can use the default "Map constructor" syntax.
If, however, you do not control property naming in either set of objects, I would still recommend a different Map-based short-cut. First define a constant Map from one set of property names to the other, like so:
def map = [param1:"jsonParam1", param2:"jsonParam2", param3:"jsonParam3",
param4:"jsonParam4", param5:"jsonParam5"]
Then I would use something like this for the object unmarshalling:
def obj = new ObjectType().with { o ->
jsonRequest.jsonWrap.attrib.something.with { j ->
map.each { oParam, jParam -> o[oParam] = j[jParam] }
}
o
}
i don't think there is a trivial way to trick groovy into "use objectA, if getting is needed and objectB for setting". If obj above is a map or you can apply a map to this object, then you could produce a map in your with block and use this. If you have to have nested structures then more work is needed.
def jsonParam = new Expando([ p1: 'p1', p2: 'p2', p3: 'p3', ])
def obj = new Expando(
jsonParam.with{
[
param1: p1,
param3: p3,
] // `with` will return this map
})
assert obj.param1==jsonParam.p1
assert obj.param3==jsonParam.p3
I use expandos for simple code.
How to add a String type field to class (i.e to all instances of that class), like grails add an id and version fields to all domain classes? If it is possible, how to specify the type of field as String / Long etc
EDIT:
The added fields are not updated in DB. how to make them persistent?
With respect to POGO, you can use ExpandoMetaClass to add/override a property/field/constructor.
class Foo{
String bar
}
//Add a field to Foo at runtime
//Type is set to String in this case
Foo.metaClass.baz = "Hello World"
//Add a method to Foo at runtime
Foo.metaClass.doSomething = {String str -> str.reverse()}
assert new Foo().baz == "Hello World"
assert new Foo().doSomething("Hello") == "olleH"
For your use case, you may be able to use normal inheritance:
abstract class Base {
// common fields
// constraints for those fields
// etc.
}
class MyDomain extends Base {
}
I've got a domain class which I want to, at run time, do a database call to populate a list of objects as a property. I have a tree with a 'headMember' property and that property is an object which has the following function:
def marriages = {
def marriages = Marriage.findAll("from Marriage as m where m.mainMember.name=:name", [name:name])
return [marriages:marriages]
}
in my GSP, I use ${tree?.headMember?.marriages} to access the 'headMember' property of the model which is passed to the view 'tree' from the following function in the relevant controller:
def show = {
def tree = Tree.get(params.id)
render(view:'show', model:[tree:tree])
}
when I view this in my browser, i get:
Member$_closure1#3708ab98
where I'd expect a list.
Any ideas what I'm doing wrong?
Cheers.
When you call marriages, you are calling a closure and this closure is returned. I think that you should rework it to be a method, something like that:
static transients = ['marriages'] // tell hibernate that marriages is not a persistent property
List<Marriages> getMarriages(){
return Marriage.findAll("from Marriage as m where m.mainMember.name=:name", [name:name])
}
This way, when you call ${tree?.headMember?.marriages} in your GSP, the getMarriages() method is called and list of marriages should be returned.