digitalmars.D.learn - How to create instance of class that get data from 2 another instance?
- Suliman (12/12) Jan 01 2015 I have instance of class, that need data from 2 another classes.
- anonymous (4/16) Jan 01 2015 Well, there's no `parseconfig` there. Do you expect the
- Suliman (6/12) Jan 02 2015 From line 30.
- Suliman (23/23) Jan 02 2015 I looked at my code and it's seems that I can create instance of
- Tobias Pankrath (2/25) Jan 02 2015 Anything declared in main() is local to main and not a global.
- Suliman (3/4) Jan 02 2015 Ok! So I need create multiple instances of the parseconfig?
- Tobias Pankrath (36/40) Jan 02 2015 Have you ever used a C-like programming language or are you a
- Suliman (5/5) Jan 02 2015 Thanks! I will try!
- Tobias Pankrath (10/15) Jan 02 2015 I think it's fine to have a global config instance. Alternatively
- Suliman (19/28) Jan 02 2015 Not fully understand. How I need to declare global config
- Suliman (30/30) Jan 02 2015 class parseConfig
- Suliman (7/7) Jan 02 2015 Oh mama mia! I did it!
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (56/61) Jan 03 2015 One good thing about D is that globals are better than other languages
- Suliman (3/3) Jan 04 2015 Ali, thanks for example, I understood it, but I am still can't
- Suliman (3/6) Jan 04 2015 But now I think that possible is mess architecture of app if I
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (56/57) Jan 04 2015 For reference, here is your code:
I have instance of class, that need data from 2 another classes. So I decided that I need to create it only after I get the data from both instance. auto mysql = new MySQL(parseconfig, seismoDownload); // the problem is here! (LOC 170) mysql need settings form parseconfig, and link from instance of seismoDownload class. But I am getting error: undefined identifier parseconfig, did you mean class p arseConfig? What I am doing wrong? http://www.everfall.com/paste/id.php?iwh4qdcqv6zi
Jan 01 2015
On Thursday, 1 January 2015 at 22:15:52 UTC, Suliman wrote:I have instance of class, that need data from 2 another classes. So I decided that I need to create it only after I get the data from both instance. auto mysql = new MySQL(parseconfig, seismoDownload); // the problem is here! (LOC 170) mysql need settings form parseconfig, and link from instance of seismoDownload class. But I am getting error: undefined identifier parseconfig, did you mean class p arseConfig? What I am doing wrong? http://www.everfall.com/paste/id.php?iwh4qdcqv6ziWell, there's no `parseconfig` there. Do you expect the `parseconfig` from line 30 or line 193 to be available in line 170?
Jan 01 2015
From line 30. In line 193 I am get in instance of class instance of parseconfig to be able to use config inside MySQL class. What I should to do in situation where for creation of class I should pass to constructor data instances from 2 different classes?What I am doing wrong? http://www.everfall.com/paste/id.php?iwh4qdcqv6ziWell, there's no `parseconfig` there. Do you expect the `parseconfig` from line 30 or line 193 to be available in line 170?
Jan 02 2015
I looked at my code and it's seems that I can create instance of MySQL in main. void main() { auto parseconfig = new parseConfig(); auto mysql = new MySQL(parseconfig, seismodownload); } In parseConfig I am creation instance of seismoDownload: class parseConfig { .... if (checkLinkCode(emsc_csem) == 200) { auto seismodownload = new seismoDownload(emsc_csem); seismodownload.parse(); } .... } So I should be able to call it in main ( I talk about "auto mysql = new MySQL(parseconfig, seismodownload);") But I am getting error: Error: undefined identifier seismodownload, did you mean class seismoDownload?
Jan 02 2015
On Friday, 2 January 2015 at 11:21:08 UTC, Suliman wrote:I looked at my code and it's seems that I can create instance of MySQL in main. void main() { auto parseconfig = new parseConfig(); auto mysql = new MySQL(parseconfig, seismodownload); } In parseConfig I am creation instance of seismoDownload: class parseConfig { .... if (checkLinkCode(emsc_csem) == 200) { auto seismodownload = new seismoDownload(emsc_csem); seismodownload.parse(); } .... } So I should be able to call it in main ( I talk about "auto mysql = new MySQL(parseconfig, seismodownload);") But I am getting error: Error: undefined identifier seismodownload, did you mean class seismoDownload?Anything declared in main() is local to main and not a global.
Jan 02 2015
Anything declared in main() is local to main and not a global.Ok! So I need create multiple instances of the parseconfig? Or please suggest me any solution, I really can't understand how to be in such situation...
Jan 02 2015
On Friday, 2 January 2015 at 14:50:54 UTC, Suliman wrote:Have you ever used a C-like programming language or are you a bloody beginner? So that I can figure out how basic the explanation has to be. Basically every pair of {} introduces a scope. And you can only refer to things declared in the current or a parent scope. { int x; { // x available here } } // x not available anymore For your example this means that void main() { auto parseconfig = new parseConfig(); } // parseConfig unavaiable since here class whatever { // cannot use parseconfig } What you can do is to declare the config outside any braces and make it a module global. But you'll need a module constructor (look them up in the docs). They are declared with this() outside of any scope in a module. ---- parseConfig parseconfig; this() { parseconfig = new parseConfig(...); } void main() { /* can use parseconfig */ } class SomeClass { /* should be able to as well */ } ---Anything declared in main() is local to main and not a global.Ok! So I need create multiple instances of the parseconfig? Or please suggest me any solution, I really can't understand how to be in such situation...
Jan 02 2015
Thanks! I will try! D is my first compilable language, I wrote only some scripts without OO before. So in my case your suggestion is best practice? Or there is any more simple way to pass config and data to MySQL class?
Jan 02 2015
On Friday, 2 January 2015 at 15:33:06 UTC, Suliman wrote:Thanks! I will try! D is my first compilable language, I wrote only some scripts without OO before. So in my case your suggestion is best practice? Or there is any more simple way to pass config and data to MySQL class?I think it's fine to have a global config instance. Alternatively you can pass the config to both the seismoDownlead and MySqlWhatever classes. // there ist enforce(cond, msg) for this in std.exception/std.conv, dunno. if (!exists(confpath)) throw new Exception("ERROR: config.ini do not exists"); // it becomes enforce(exists(confpath), "ERROR: config.ini does not exist");
Jan 02 2015
I think it's fine to have a global config instance. Alternatively you can pass the config to both the seismoDownlead and MySqlWhatever classes. // there ist enforce(cond, msg) for this in std.exception/std.conv, dunno. if (!exists(confpath)) throw new Exception("ERROR: config.ini do not exists"); // it becomes enforce(exists(confpath), "ERROR: config.ini does not exist");Not fully understand. How I need to declare global config instance? void main() { } this() { auto parseconfig = new parseConfig(); } But how this() will be called in nothing in main? And I can't understand how to pass the config to both the seismoDownlead and MySqlWhatever classes. I know how to pass, but I do not understand how to do it with current situation with scopes. Here is current version of my code. I am not asking to do work for me, but could you show what and where I should move http://www.everfall.com/paste/id.php?oscnkeq740ue ?
Jan 02 2015
class parseConfig { string dbname; string dbuser; string dbpass; string dbhost; string dbport; uint status; this() { auto checkLinkCode(string link) // we need to check all links to be sure if they are alive { .... return status; } ............. if (checkLinkCode(emsc_csem) == 200) { auto seismodownload = new seismoDownload(emsc_csem, this); //here seismodownload.parse(); } } } of class from where it's call (Here is parseConfig). Is it's possible to do something similar in D?
Jan 02 2015
Oh mama mia! I did it! http://www.everfall.com/paste/id.php?a5pp73ns1e4k auto seismodownload = new seismoDownload(emsc_csem, this); then: auto mysql = new MySQL(parseconfig,eqs); So could anybody show me better way? As I said I did not fully understand how use global class instance...
Jan 02 2015
On 01/02/2015 12:42 PM, Suliman wrote:auto seismodownload = new seismoDownload(emsc_csem, this); then: auto mysql = new MySQL(parseconfig,eqs); So could anybody show me better way?Yes, there is a better way.As I said I did not fully understand how use global class instance...One good thing about D is that globals are better than other languages because they are actually module-global and by default thread-local. Module-global means that there more than one module can use the same name for their respective globals; thread-local means that implicit data-sharing is prevented. However, module-globals can be harmful as well because depending on the design, they prevent functions from being reentrant and prevent having more than one of that resource. For that reason, it is usually better to provide the resource to its consumers e.g. as constructor parameters. Instead of this: string fileName; // <-- May be a problem static this() { /* Just to assume that we need a run time value. */ import std.random; import std.string; fileName = format("file_%s", uniform(0, 1000)); } struct S { void foo() { /* Assume that it uses fileName. It would be at least * confusing if there were more than one instance of * S. Which one would be using fileName when? */ } } void main() { auto s = S(); s.foo(); } Prefer this: struct S { string fileName; // <-- Takes it as a run-time argument // (Could be constructor parameter as well.) void foo() { /* Now it would be using its own fileName, which might * be provided to more than one object but then it * might be acceptable, presumably because it was * according to design. */ } } void main() { import std.random; import std.string; auto s = S(format("file_%s", uniform(0, 1000))); s.foo(); } Ali
Jan 03 2015
Ali, thanks for example, I understood it, but I am still can't understand how to write code above without passing this as parameter...
Jan 04 2015
On Sunday, 4 January 2015 at 15:37:53 UTC, Suliman wrote:Ali, thanks for example, I understood it, but I am still can't understand how to write code above without passing this as parameter...But now I think that possible is mess architecture of app if I meet such problem...
Jan 04 2015
On 01/04/2015 07:37 AM, Suliman wrote:how to write code above without passing this as parameter...For reference, here is your code: http://www.everfall.com/paste/id.php?a5pp73ns1e4k There is nothing fundamentally wrong in a class constructor passing 'this' to an object that it constructs: class A { B b; this() { b = new B(this); // Makes its B } } However, keep in mind that 'this' is not an A until we leave the constructor. For that reason, the B's constructor must not use the A reference that it receives. In that code, apparently A owns a B for its purposes. Presumably, that is why A's constructor is creating a B object. Commonly, it is either not the case or even if so, we want to provide a B from "above" so that A becomes testable. (Search for "parametrize from above" by "kevlin henney"; or search for "dependency injection".) So, usually the following idiom is prefered: class A { B b; this(B b) { this.b = b; // Takes its B as a parameter } } Well, it works fine until you need both of the objects to refer to each other: class A { B b; this(B b) { this.b = b; } } class B { A a; this(A a) { this.a = a; } } It is impossible to construct two objects at the same, which refer to each other: auto a = new A(/* where is my B? */); // Oops! auto b = new B(a); So, A must not have an invariant that requires non-null B and that it must have a property to set the B later on: auto a = new A(null); // Here, A must be happy with null B auto b = new B(a); a.b = b; // Finally, we have two happy objects So, your code is just fine because there is no general solution anyway. Ali
Jan 04 2015