I have these 2 methods in the same class, and I want to access a variable inside the second method. in C# we just set it to public variable.. but what about Dart and Flutter.. how to access this variable 'hours' in play method.
This is the way I tried but it tells me that it cannot recognize hours variable.
The problem is 'hours' variable is final and can not be declared at class level because it needs to be initialized and I want to initialize it only inside study method
class Student{
Future study(){
final hours = 5;
}
void play(){
int playhours = study().hours +2;
}
}
You cannot just make the variable global that you defined inside a function. What I normally do is that if I need to access a variable that will be set in another function of my class then I will define the variable outside the function and call it later when I need it. For your example I would do this:
class Student{
int hours;
Future study(){
hours = 5;
}
void play(){
//study(); You can call the function inside this one if you want
int playhours = hours + 2;
print(playhours.toString()); // Output: 7
}
}
Then when calling it:
void main() {
Student student = Student();
//student.study(); If you use it separately
student.play();
}
Another thing you could do is to return the value in your study() function!
Easy just do it like this:
class Student{
int hours;
Future study(){
hours = 5;
}
void play(){
//study(); You can call the function inside this one if you want
int playhours = hours + 2;
print(playhours.toString()); // Output: 7
}
}
then call it from the main function like this:
void main() {
Student().play();
}
Related
This question already has an answer here:
Is there a difference in how member variables are initialized in Dart?
(1 answer)
Closed 1 year ago.
I'm trying to understand the following example where I try to initialize a final variable in a constructor.
1st example - works
void main() {
Test example = new Test(1,2);
print(example.a); //print gives 1
}
class Test
{
final int a;
int b;
Test(this.a, this.b);
}
2nd example doesn't work
void main() {
Test example = new Test(1,2);
print(example.a); //compiler throws an error
}
class Test
{
final int a;
int b;
Test(int a, int b){
this.a = a;
this.b = b;
}
}
and when i remove final then it works again
void main() {
Test example = new Test(1,2);
print(example.a); //print gives 1
}
class Test
{
int a;
int b;
Test(int a, int b){
this.a = a;
this.b = b;
}
}
what is the difference between the constructor in the 1st and the 2nd constructor why final initialization works with the first and doesn't with the 2nd.
Can anyone explain that to me please?
THanks
You cannot instantiate final fields in the constructor body.
Instance variables can be final, in which case they must be set exactly once. Initialize final, non-late instance variables at declaration, using a constructor parameter, or using a constructor’s initializer list:
Declare a constructor by creating a function with the same name as
its class (plus, optionally, an additional identifier as described in
Named constructors). The most common form of constructor, the
generative constructor, creates a new instance of a class
syntax in the constructor (described in https://www.dartlang.org/guides/language/language-tour#constructors):
My question refers to Methods inside of Classes via "public" access.
As referring to mql4 documentation, there seems to be no listed source on how to properly instantiate a Method into a Class, or what even makes a Method a Method in the first place.
To me it seems that if you place a function inside of a Class, that in itself makes it a Method? Or am I wrong. Is anyone able to clear this up for me?
Basic information and differences between constructor and method:
Constructor:
A constructor is a special function, which is called automatically when creating an object of a structure or class and is usually used to initialize class members,
The name of a constructor must match the class name,
The constructor has no return type (you can specify the void type).
(docs)
Method:
A method is a function that belongs to a class or an object, i.e. it cannot exist without the class.
You need to declare class methods in the class. Else it wouldn't be a class method.
Method can return value with type specified in the method declaration.
Simple example:
class MyClass { // Declaration
private:
string myName; // Property
public:
void printName(); // Method of void return type
int sumIntegers(int a, int b); // Method of int return type
MyClass(string name); // Constructor declaration
};
MyClass::MyClass(string name) { // Constructor body
this.myName = name;
}
int MyClass::sumIntegers(int a, int b) { //Method body
return a + b;
}
void MyClass::printName() {
Print("Your name is: ", this.myName);
}
int sumIntegers(int a, int b){ //Function body
return a + b;
}
Class member (object) initialization:
MyClass *myObject = new MyClass("SO example");
Example usage inside OnInit:
int OnInit() {
myObject.printName(); // Method call by object (MyClass)
Alert("2 + 2 = ", myObject.sumIntegers(2, 2)); // Same as above
Alert("2 + 2 = ", sumIntegers(2, 2)); // Function call
return(INIT_SUCCEEDED);
}
To me it seems that if you place a function inside of a Class, that in
itself makes it a Method?
Yes, but remember that a function is a block of code which only runs when it is called, and it's not related with a class.
Methods are related with class, and can not exists without a class.
I have multiple class like this:-
Class A {
static int xyz = 10;
int c;
int d;
static A getData() {
// Do something
return A()..c = xyz*5;
}
Class B {
static int abc = 10;
int c;
static B getData() {
// Do something
return B()..c = xyz*5;
}
So, here you can see that the the getData() is doing the same thing, but have different return types.
Is there any way to avoid duplicate implementation like this, can it be done by defining a single function which can reference the class and have multiple return type?
This has two parts: creating the object, and assigning to a field of the object.
Creating the object, you are mostly out of luck. The only way to create an object of a specific type in a generic method is by using reflection via dart:mirrors. However, you have indicated that this is for a Flutter project, and Flutter doesn't support reflection, so that isn't an option. The only way you are going to be able to dynamically create an object is to pass in a factory method that the generic method can call to construct the object.
Assigning to a field of the object is easier, but it requires that you either lose static type checking by using dynamic or by tying your classes together with inheritance. The latter is the preferable choice, but if you are working with a library than it isn't always an option.
Combining these two things, the code will look like this:
class Foo {
static int xyz = 10;
int c;
}
class A extends Foo {
int d;
static A getData() {
return modifyObject(() => A());
}
}
class B extends Foo {
static B getData() {
return modifyObject(() => B());
}
}
T modifyObject<T extends Foo>(T create()) {
return create()..c = Foo.xyz * 5;
}
Before doing this, though, I'd take a look at whether your project actually needs it. If your use case is as simple as your example, I would argue that this level of generalization is overkill and you are hurting your code's readability more than you are helping its modularity.
In my game I programmatically create a bunch of buttons for a level select screen, and my intention was to have their onClick fire a function with a parameter that corresponds to level number.
Pseudocode:
public class UIManager extends MonoBehaviour {
public var button : Transform;
public function Start() {
for(var i : int = 0; i < 10; i++) {
var level : int = i + 1;
var b : Transform = Instantiate(button);
b.GetComponent(UI.Button).onClick.AddListener(function(){
StartGame(level);
});
}
}
public function StartGame(level : int) {
Debug.Log(level);
}
}
However, in this situation, when any of these buttons is pressed, the console shows number 10.
How can I achieve what I'm aiming for?
You should have a look at how anonymous functions in JavaScript capture outer variables.
You are creating 10 anonymous functions in your for-loop. All these functions refer to the local variable level. However, they do not yet create their own scope for this variable until they are first called. This means, there is not 10 level locals, but only one until the first function is actually called. Only then will the current value of level be evaluated. And this will be the value it was assigned last: 10.
To get around this you'll have to force creation of a new scope during every iteration of the loop:
public class UIManager extends MonoBehaviour
{
public var button : Transform;
public function Start()
{
for(var i : int = 0; i < 10; i++)
{
var level : int = i + 1;
var b : Transform = Instantiate(button);
b.GetComponent(UI.Button).onClick.AddListener
(
(function(newLocalLevel)
{
return function()
{
StartGame(newLocalLevel);
};
}) (level)
);
}
}
public function StartGame(level : int)
{
Debug.Log(level);
}
}
I changed your direct assigned of an anonymous handler function to a factory function call, which takes the current (!) value of level as a parameter. As it is immediately executed, the factory function creates its own scope, with an own local called newLocalLevel that carries the correct value of level.
The factory function now creates and returns your anonymous handler function, which, even though it not yet creates its own scope, refers to the local newLocalLevel of the enclosing factory function, which has one seperate scope for every iteration of the loop.
See also http://www.mennovanslooten.nl/blog/post/62.
I have an object with a number of properties.
I want to be able to assign some of these properties when I call the constructor.
The obvious solution is to either have a constructor that takes a parameter for each of the properties, but that's nasty when there are lots. Another solution would be to create overloads that each take a subset of property values, but I could end up with dozens of overloads.
So I thought, wouldn't it be nice if I could say..
MyObject x = new MyObject(o => o.Property1 = "ABC", o.PropertyN = xx, ...);
The problem is, I'm too dim to work out how to do it.
Do you know?
C# 3 allows you to do this with its object initializer syntax.
Here is an example:
using System;
class Program
{
static void Main()
{
Foo foo = new Foo { Bar = "bar" };
}
}
class Foo
{
public String Bar { get; set; }
}
The way this works is that the compiler creates an instance of the class with compiler-generated name (like <>g__initLocal0). Then the compiler takes each property that you initialize and sets the value of the property.
Basically the compiler translates the Main method above to something like this:
static void Main()
{
// Create an instance of "Foo".
Foo <>g__initLocal0 = new Foo();
// Set the property.
<>g__initLocal0.Bar = "bar";
// Now create my "Foo" instance and set it
// equal to the compiler's instance which
// has the property set.
Foo foo = <>g__initLocal0;
}
The object initializer syntax is the easiest to use and requires no extra code for the constructor.
However, if you need to do something more complex, like call methods, you could have a constructor that takes an Action param to perform the population of the object.
public class MyClass
{
public MyClass(Action<MyClass> populator)
{
populator.Invoke(this);
}
public int MyInt { get; set; }
public void DoSomething()
{
Console.WriteLine(this.MyInt);
}
}
Now you can use it like so.
var x = new MyClass(mc => { mc.MyInt = 1; mc.DoSomething(); });
Basically what Andrew was trying to say is if you have a class (MyObject for eg) with N properties, using the Object Initializer syntax of C# 3.0, you can set any subset of the N properties as so:
MyObject x = new MyObject {Property1 = 5, Property4 = "test", PropertyN = 6.7};
You can set any of the properties / fields that way./
class MyObject
{
public MyObject(params Action<MyObject>[]inputs)
{
foreach(Action<MyObject> input in inputs)
{
input(this);
}
}
}
I may have the function generic style wrong, but I think this is sort of what you're describing.