www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to create instance of class that get data from 2 another instance?

reply "Suliman" <evermind live.ru> writes:
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
parent reply "anonymous" <anonymous example.com> writes:
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?iwh4qdcqv6zi
Well, 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
parent reply "Suliman" <evermind live.ru> writes:
 What I am doing wrong?

 http://www.everfall.com/paste/id.php?iwh4qdcqv6zi
Well, there's no `parseconfig` there. Do you expect the `parseconfig` from line 30 or line 193 to be available in line 170?
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?
Jan 02 2015
parent reply "Suliman" <evermind live.ru> writes:
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
parent reply "Tobias Pankrath" <tobias pankrath.net> writes:
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
parent reply "Suliman" <evermind live.ru> writes:
 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
parent reply "Tobias Pankrath" <tobias pankrath.net> writes:
On Friday, 2 January 2015 at 14:50:54 UTC, Suliman wrote:
 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...
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 */ } ---
Jan 02 2015
parent reply "Suliman" <evermind live.ru> writes:
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
parent reply "Tobias Pankrath" <tobias pankrath.net> writes:
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
parent reply "Suliman" <evermind live.ru> writes:
 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
parent reply "Suliman" <evermind live.ru> writes:
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();
	}

		
}
}


I know that in ะก# I can pass to function, and this would be point 
of class from where it's call (Here is parseConfig). Is it's 
possible to do something similar in D?
Jan 02 2015
parent reply "Suliman" <evermind live.ru> writes:
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
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
parent reply "Suliman" <evermind live.ru> writes:
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
next sibling parent "Suliman" <evermind live.ru> writes:
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
prev sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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