How to set a class wide variable? - xcode

Just starting with Swift, I'm creating an API service class but I don't understand how I can make this work!?!
import UIKit
class Hello {
var className: String
init() {
self.className = "hello"
}
class func someFunc() {
println(self.className = "hello") // <= This doesn't work
}
}
From what I understand, since I need someFunc to be accessible when I call it, I need it to have class func. Example, in my view controller, when the user clicks a button, I can do Hello.someFunc().
Thanks in advance for your help.

If you want to allow subclasses to be able to override it:
class var className: String { return "Hello" }
(Note that class variables cannot be stored properties; they must be computed properties.)
Otherwise:
static var className = "Hello"
(static is the same as final class)
You can read more about type properties in the Swift Programming Language book.
Your current println is failing because you're trying to print an assignment, rather than a string. I suspect you meant something more like:
println("ClassName is \"\(className)\"")
Although — having said all of that — if you just want to get the name of the class you ought to use:
println(self.dynamicType)

You would need to declared class variable as static that way, you can access it inside your class level methods using self. However, if you want to access that from instance method you will have to use class name with it.
class Hello {
static var className: String = ""
init() {
Hello.className = "hello"
}
class func someFunc() {
println(self.className = "hello")
}
}
Also notice that swift expects that the class variable are initialized when they are created.

Related

How to create single observable value?

I've got a top-level Controller object that is holding a reference to three objects (MyObject). I'd like to position these precisely on the page at any time, but I would like each object to also be editable, and I'm not really sure how to do that.
So far, I've got a class that extends ItemFragment and displays my individual items, like this:
class MyObjectFragment(o: MyObject) : ItemFragment<MyObject>() {
override val root = hbox {
...
}
}
Meanwhile, I have a top-level View with a reference to my controller, like this:
class TopLevelView : View() {
val controller = TopLevelController()
override val root = hbox {
add(MyObjectFragment(controller.myObject1))
...
add(MyObjectFragment(controller.myObject2))
...
add(MyObjectFragment(controller.myObject3))
}
}
And right now, all I have for the top level controller is this:
class TopLevelController() : Controller() {
val myObject1 = MyObject()
val myObject2 = MyObject()
val myObject3 = MyObject()
}
I'm trying to figure out what I need to do to wrap these objects as observable values. My first attempt was to add something like this to the init method of MyObjectFragment:
class MyObjectFragment(o: MyObject) : ItemFragment<MyObject>() {
init {
itemProperty.bind(o)
}
...
}
However, that method only takes an ObservableValue<MyObject>. What is the best way to get that to tie all of this together?
You can create an observable list of your objects like so:
class TopLevelController() : Controller() {
val myObjects = FXCollections.observableArrayList<MyObject>(MyObject(), MyObject(), MyObject())
}
Then in your TopLevelView, you can bind this list to a layout node's children property, and inflate the proper Fragment for each object:
class TopLevelView : View() {
val controller = TopLevelController()
override val root = hbox {
bindChildren(controller.myObjects) {
MyObjectFragment(it).root
}
}
}
I'll admit your requirements seem a little vague to me without more information. It'd be helpful to know more of what you want from the item fragments. Are they going to be in a list view or table? Or something more dynamic? And how exactly would they be editing? Would there be a save button or would you expect any input to commit those changes immediately?
import tornadofx.*
class MyObject() {
//val someProperty = SimpleObjectProperty<Something>()
//var some by someProperty
}
class MyObjectModel(myObject: MyObject? = null) : ItemViewModel<MyObject>(myObject) {
//val someBinding = bind(MyObject::someProperty)
}
class MyObjectFragment : ItemFragment<MyObject>() {
val model: MyObjectModel by inject()
override val root = hbox {
label("This is an MyObject Fragment")
//you would bind some control to the model binding in here. For example:
//textfield(model.someBinding)
}
init {
itemProperty.value = model.item
model.bindTo(this)
}
}
class TopLevelController : Controller() {
val myObject1 = MyObject()
val myObject2 = MyObject()
val myObject3 = MyObject()
}
class TopLevelView : View() {
val controller: TopLevelController by inject()
override val root = vbox {
add(setUpObjectFragment(controller.myObject1))
add(setUpObjectFragment(controller.myObject2))
add(setUpObjectFragment(controller.myObject3))
}
fun setUpObjectFragment(obj: MyObject) = find<MyObjectFragment>(Scope(MyObjectModel(obj)))
}
It also seems you're new and are missing a lot of key concepts to utilize from TornadoFX. Using find for instance, is really important for Fragments and Views so they have the proper life cycle.
Then there's Scopes which help with being able to call certain Components with injection.
And finally, there are Model classes, most importantly ItemViewModel which gives you the most functionality with editing, like being able to rollback and commit changes as well as to mark properties as required and add validate filters.
If this isn't a satisfactory solution, please give us more information on what you want, as I might be able to provide a more elegant and concise solution. If these concepts are confusing, please look at Edvin's guide.

How object member's address is figured out on a method call?

I know the question is a bit generic but I need a generic answer already. So the thing I'am trying to understand is how an object's member variable is accessed from the memory point of view, for example, when a method is called on that object?
For example, I've this simple class;
class Hoo {
public int field;
// constructor, setters, getters
...
}
class Foo {
Hoo hoo;
void setHoo() {
hoo = new Hoo(...)
}
}
how runtime would figure out the memory address of hoo even before it's initialised? Same applies also the below code;
class Foo {
Hoo hoo = new Hoo();
void setHooField() {
hoo.field = 5;
}
}
How would the runtime know the field's address here to store a value on it?
IMO, for Java at least, these variable addresses are mapped to an offset in the class file so the exact location (on virtual memory) can be figured out by adding this offset to the passed object reference (into the virtual method). But no sure...
Any ideas?

How do I correctly bind?

I have a class MyClass, which implements INotifyPropertyChanged, and it has some properties that must be bound in some page. In my page I have
private MyClass myclass;
and in the page constructor I write
ContentPanel.DataContext = myclass;
When I assign myclass to some MyClass object, which I get from some callback, nothing is shown in page.
But when I write the properties that I must change instead of MyClass class in page.cs and bind them it work correctly.
Or when I give
ContentPanel.DataContext = this;
and in xaml I write
{binding this.myclass.property}
it also works correctly.
Here is callback
public void GetCommonInfoCallback(UserCommonInfo userCommonInfo)
{
CommonInfo = userCommonInfo;
}
where UserCommonInfo is MyClass, and CommonInfo is myclass.
private UserCommonInfo userCommonInfo ;
public UserCommonInfo CommonInfo
{
get
{
return userCommonInfo;
}
set
{
if (userCommonInfo != value)
{
userCommonInfo = value;
OnPropertyChanged("CommonInfo");
}
}
}
I can't understand where is my mistake. Can you help me?
When you set DataContext, it is the specific instance of MyClass that is used for data binding. So after executing
ContentPanel.DataContext = myclass;
you could later execute
myclass.someProperty = "new value of someProperty";
and the data will be updated in the bound control (assuming this is not a OneTime binding, but OneWay or TwoWay binding instead).
If I understand you question correctly, you want to change the binding to use a different instance of MyClass.
myclass = new MyClass { /* ... */ }; // new instance of MyClass
At this point, the controls are still bound to the previous instance of MyClass. You can change that by updating the DataContext:
DataContext = myclass; // set context to the new MyClass instance
The second approach that you wrote, with
ContentPanel.DataContext = this;
represents a different style, where you are making the page class also serve as the data model instance for data binding.
In this case, you are not changing the data binding to use a new instance of the data model (the page instance, 'this', is not changing). IMHO, there is very valuable to separate the page and the data model, so I prefer to not use the DataContext = this approach.

Non-static method cannot be referenced from a static context

I'm trying to call a method from another class and from what I've gathered, the method I'm trying to call is an instance method. I've gathered that, that means it uses instance variables of an object. Is there an easy way to call this method?
This is the main method,
public void main()
{
Test.testPetOwner();
}
And this is the method I'm trying to call in a class called "Test"
public void testPetOwner()
{
String petName;
String species;
String hairCondition;
String posture;
testCompetitor();
PetOwner petOwner1 = new PetOwner();
System.out.println("What is the pet's name?");
petName = Genio.getString();
petOwner1.setPetName(petName);
System.out.println("What is the species of the pet?");
species = Genio.getString();
petOwner1.setSpecies(species);
System.out.println("What is the hair condition of the pet?");
hairCondition = Genio.getString();
petOwner1.setHairCondition(hairCondition);
System.out.println("How is the pet's posture?");
posture = Genio.getString();
petOwner1.setPosture(posture);
}
public void main()
{
Test t = new Test();
t.testPetOwner();
}
If we try to access an instance method from a static context , compiler has now way to guess which instance method ( variable for which object ), you are referring too. Though you can always access it using object reference.

How can I apply the "move method" refactoring with IntelliJ IDEA?

I want to be able to move an instance method from one class to another class ("Move method" from Fowler's "Refactoring") in IntelliJ IDEA. Unfortunately, when I try "Move..." (cmd: F6), it tells me that "There are no methods that have a reference type. Would you like to make method static and then move?" I do not want to make my method static, I want it to be an instance method on the other class instead.
My code example:
public class TheClass {
public void doStuff(){
int i = themethod();
}
private int theMethod() {
System.out.println( "Hello World!" );
return 0;
}
}
public class OtherClass {
}
Say I want to move theMethod from TheClass to OtherClass. Is there an automatic refactoring in IDEA for this, and if so: How do I apply it?
In IntelliJ 14-15 do the following:
Position the caret on theMethod().
press Ctrl/Cmd+F6 (Change signature).
Introduce new parameter: Type=TheOtherClass, Name=theOtherClass, Default value=new TheOtherClass()
Refactor
Then press F6 (move) and move the method to theOtherClass.
You will end up with:
public class TheClass {
public void doStuff() {
int i = new TheOtherClass().theMethod();
}
}
public class TheOtherClass {
int theMethod() {
System.out.println("Hello World!");
return 0;
}
}
The Move Method refactoring in IDEA only considers moving the method into classes related to it, i.e. used as its parameter or return value, or called from inside the method. Which is kinda logical: if the method has nothing concrete to do with the target class, why should it be there? OTOH I found this limiting in some cases where I still had a valid reason to move the method. So I had to do it by hand.
In intellij 13.1 (dont' know in previous version) it could be done with the
Choose Refactor | Extract | Delegate on the main menu
but there is a "strange" limit, apparently: it could be done only with a new freshly created class.
So you have to do apply this refactoring without creating the "OtherClass" (it will be create directly when you apply the refactoring).
So a real "move" of method on an alredy created class seems missing, quite strange behaviou
if theMethod() has nothing reference to the host class(TheClass), you can make this method static and then use "Move" command. After the method was moved to the target class, you should remove the static keyword.
There is another method. Imagine you have the code:
public int field;
public void foo(int a) {
assert field == a;
}
And you want to make foo static. Select the whole body of the method and preess Alt+Ctrl+M (Extract method). Type the same name of the method. Check "Declare static" checkbox (available only if the method only reads and doesn't modify the fields) and press Ok. So you get:
public void foo(int a) {
foo(a, field);
}
private static void foo(int a, int field) {
assert field == a;
}
Move static method wherever you want and use old foo's body to call it.

Resources