Thread overview | |||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
October 12, 2015 Class, constructor and inherance. | ||||
---|---|---|---|---|
| ||||
Hello I'm trying to write my first class. I want to use it as module and build anothers on top of it. I read that default functions attributes are not inherited. Is it that same for constructor? This is how my class (not finished) is looking right now: class credential { auto accessKey = environment.get["AWS_ACCESS_KEY"]; auto secretKey = environment.get["AWS_SECRET_KEY"]; } class sigv4 : credential { public: string method; string service; string host; string region; string endpoint; string request_parameters; string payload; private: const algorithm = "AWS4-HMAC-SHA256"; auto currentClock = Clock.currTime(UTC()); auto currentDate = cast(Date)currentClock; auto curDateStr = currentDate.toISOString; auto currentTime = cast(TimeOfDay)currentClock; auto curTimeStr = currentTime.toISOString; auto xamztime = curDateStr ~ "T" ~ curTimeStr ~ "Z"; auto hmac_sha256(ubyte[] key, ubyte[] msg) { auto hmac = hmac!SHA256(key); hmac.put(msg); auto digest = hmac.finish; return digest; } auto getSignatureKey(string key, string dateStamp, string regionName, string serviceName) { ubyte[] kString = cast(ubyte[])("AWS4" ~ key); auto kDate = sign(kString, cast(ubyte[])dateStamp); auto kRegion = sign(kDate, cast(ubyte[])regionName); auto kService = sign(kRegion, cast(ubyte[])serviceName); auto kSigning = sign(kService, cast(ubyte[])"aws4_request"); return kSigning; } auto getCanonicalRequest(string canonicalURI, string canonicalQueryString, string canonicalHeaderString, string signedHeaders) { string payloadHash = sha256Of("").toHexString.toLower; string canonicalRequest = method ~ "\n" ~ canonicalURI ~ "\n" ~ canonicalQueryString ~ "\n" ~ canonicalHeadersString ~ "\n" ~ signedHeaders ~ "\n" ~ payloadHash; } this() { } } I need to set all variables by defaults values from "public" and all needed by function "getCanonicalRequest". But if i will use that class to build another should i set defaults again? If yes is there some solution for it? //holo |
October 12, 2015 Re: Class, constructor and inherance. | ||||
---|---|---|---|---|
| ||||
Posted in reply to holo | On 12/10/15 3:14 PM, holo wrote: > Hello > > I'm trying to write my first class. I want to use it as module and build > anothers on top of it. I read that default functions attributes are not > inherited. Is it that same for constructor? This is how my class (not > finished) is looking right now: > > class credential > { > auto accessKey = environment.get["AWS_ACCESS_KEY"]; > auto secretKey = environment.get["AWS_SECRET_KEY"]; > } > > class sigv4 : credential > { > public: > string method; > string service; > string host; > string region; > string endpoint; > string request_parameters; > string payload; > > private: > const algorithm = "AWS4-HMAC-SHA256"; > > auto currentClock = Clock.currTime(UTC()); > auto currentDate = cast(Date)currentClock; > auto curDateStr = currentDate.toISOString; > auto currentTime = cast(TimeOfDay)currentClock; > auto curTimeStr = currentTime.toISOString; > auto xamztime = curDateStr ~ "T" ~ curTimeStr ~ "Z"; > > auto hmac_sha256(ubyte[] key, ubyte[] msg) > { > auto hmac = hmac!SHA256(key); > hmac.put(msg); > auto digest = hmac.finish; > > return digest; > } > > auto getSignatureKey(string key, string dateStamp, string > regionName, string serviceName) > { > ubyte[] kString = cast(ubyte[])("AWS4" ~ key); > auto kDate = sign(kString, cast(ubyte[])dateStamp); > auto kRegion = sign(kDate, cast(ubyte[])regionName); > auto kService = sign(kRegion, cast(ubyte[])serviceName); > auto kSigning = sign(kService, cast(ubyte[])"aws4_request"); > > return kSigning; > } > > auto getCanonicalRequest(string canonicalURI, string > canonicalQueryString, string canonicalHeaderString, string signedHeaders) > { > string payloadHash = sha256Of("").toHexString.toLower; > string canonicalRequest = method ~ "\n" ~ canonicalURI ~ > "\n" ~ canonicalQueryString ~ "\n" ~ canonicalHeadersString ~ "\n" ~ > signedHeaders ~ "\n" ~ payloadHash; > } > > this() > { > > } > } > > I need to set all variables by defaults values from "public" and all > needed by function "getCanonicalRequest". But if i will use that class > to build another should i set defaults again? If yes is there some > solution for it? > > //holo By the looks, I'm guessing you do not have much experience when it comes to OOP. I think you are wanting something a bit closer to: import std.typecons : tuple, TypeTuple; interface Credential { string encode(....); } class SigV4 : Credential { this(....) { .... } string encode(....) { } private: .... } TypeTuple!(string, string) AWSKeys() { import std.process; return tuple(environment.get("AWS_ACCESS_KEY"), environment.get("AWS_SECRET_KEY")); } |
October 12, 2015 Re: Class, constructor and inherance. | ||||
---|---|---|---|---|
| ||||
Posted in reply to holo | On Monday, 12 October 2015 at 02:14:35 UTC, holo wrote:
> class credential
> {
> auto accessKey = environment.get["AWS_ACCESS_KEY"];
> auto secretKey = environment.get["AWS_SECRET_KEY"];
> }
>
> class sigv4 : credential
> {
> private:
> const algorithm = "AWS4-HMAC-SHA256";
>
> auto currentClock = Clock.currTime(UTC());
> auto currentDate = cast(Date)currentClock;
> auto curDateStr = currentDate.toISOString;
> auto currentTime = cast(TimeOfDay)currentClock;
> auto curTimeStr = currentTime.toISOString;
> auto xamztime = curDateStr ~ "T" ~ curTimeStr ~ "Z";
> }
You should set these in the constructor rather than in the class body (the only one that's okay to intialize here is `algorithm`, as it's a const string).
|
October 12, 2015 Re: Class, constructor and inherance. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Rikki Cattermole | >
> By the looks, I'm guessing you do not have much experience when it comes to OOP.
>
> I think you are wanting something a bit closer to:
>
> import std.typecons : tuple, TypeTuple;
>
> interface Credential {
> string encode(....);
> }
>
> class SigV4 : Credential {
> this(....) {
> ....
> }
>
> string encode(....) {
>
> }
>
> private:
> ....
> }
>
>
> TypeTuple!(string, string) AWSKeys() {
> import std.process;
> return tuple(environment.get("AWS_ACCESS_KEY"), environment.get("AWS_SECRET_KEY"));
> }
Yes you guessed good, i don't have any experience with OOP (i have some experience with C - simple AVR projects and tons of bash scripts) this is my first such kind of language which I'm trying to learn. For beginning I'm trying to avoid advanced things like templates or from your example touples (Touples looks for me like some kind of array but every cell can be different type, am i right? Eg tuple from your example is that same what string[2] var?) i was reading about it but for now i can't understand what they are and for what they are useful.
I'm trying to learn on the examples and honestly i'm not understand how that TypeTuple is resolving my problem with default values for classes?
Second thing that interfaces, are they needed? Without it you can write same function just compilator wont be screaming for it lack.
|
October 12, 2015 Re: Class, constructor and inherance. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | On Monday, 12 October 2015 at 02:30:43 UTC, Meta wrote: > On Monday, 12 October 2015 at 02:14:35 UTC, holo wrote: >> class credential >> { >> auto accessKey = environment.get["AWS_ACCESS_KEY"]; >> auto secretKey = environment.get["AWS_SECRET_KEY"]; >> } >> >> class sigv4 : credential >> { >> private: >> const algorithm = "AWS4-HMAC-SHA256"; >> >> auto currentClock = Clock.currTime(UTC()); >> auto currentDate = cast(Date)currentClock; >> auto curDateStr = currentDate.toISOString; >> auto currentTime = cast(TimeOfDay)currentClock; >> auto curTimeStr = currentTime.toISOString; >> auto xamztime = curDateStr ~ "T" ~ curTimeStr ~ "Z"; >> } > > You should set these in the constructor rather than in the class body (the only one that's okay to intialize here is `algorithm`, as it's a const string). I rewrite it to something like this: module sigawsv4 import std.stdio, std.process; import std.digest.sha, std.digest.hmac; import std.string; import std.conv; import std.datetime; import std.net.curl; class credential { auto accessKey = environment.get["AWS_ACCESS_KEY"]; auto secretKey = environment.get["AWS_SECRET_KEY"]; } class sigv4 : credential { this(string URI = "/", string queryStr = "Action=DescribeInstances&Version=2013-10-15", string headerStr = "host:" ~ host ~ "\n" ~ "x-amz-date:" ~ xamztime ~ "\n", string headers = "host;x-amz-date") { auto currentClock = Clock.currTime(UTC()); auto currentDate = cast(Date)currentClock; auto curDateStr = currentDate.toISOString; auto currentTime = cast(TimeOfDay)currentClock; auto curTimeStr = currentTime.toISOString; auto xamztime = curDateStr ~ "T" ~ curTimeStr ~ "Z"; string canonicalURI = URI; string canonicalQueryString = queryStr; string canonicalHeaderString = headerStr; string signedHeaders = headers; } public: string method; string service; string host; string region; string endpoint; string request_parameters; string payload; private: const algorithm = "AWS4-HMAC-SHA256"; auto currentClock = Clock.currTime(UTC()); auto currentDate = cast(Date)currentClock; auto curDateStr = currentDate.toISOString; auto currentTime = cast(TimeOfDay)currentClock; auto curTimeStr = currentTime.toISOString; auto xamztime = curDateStr ~ "T" ~ curTimeStr ~ "Z"; auto hmac_sha256(ubyte[] key, ubyte[] msg) { auto hmac = hmac!SHA256(key); hmac.put(msg); auto digest = hmac.finish; return digest; } auto getSignatureKey(string key, string dateStamp, string regionName, string serviceName) { ubyte[] kString = cast(ubyte[])("AWS4" ~ key); auto kDate = sign(kString, cast(ubyte[])dateStamp); auto kRegion = sign(kDate, cast(ubyte[])regionName); auto kService = sign(kRegion, cast(ubyte[])serviceName); auto kSigning = sign(kService, cast(ubyte[])"aws4_request"); return kSigning; } auto getCanonicalRequest(string canonicalURI, string canonicalQueryString, string canonicalHeaderString, string signedHeaders) { string payloadHash = sha256Of("").toHexString.toLower; string canonicalRequest = method ~ "\n" ~ canonicalURI ~ "\n" ~ canonicalQueryString ~ "\n" ~ canonicalHeadersString ~ "\n" ~ signedHeaders ~ "\n" ~ payloadHash; } } Is right now that constructor ok? My question was too if now i will inherit that class, will that default values be in child class available? |
October 12, 2015 Re: Class, constructor and inherance. | ||||
---|---|---|---|---|
| ||||
Posted in reply to holo | On 12/10/15 4:13 PM, holo wrote: >> >> By the looks, I'm guessing you do not have much experience when it >> comes to OOP. >> >> I think you are wanting something a bit closer to: >> >> import std.typecons : tuple, TypeTuple; >> >> interface Credential { >> string encode(....); >> } >> >> class SigV4 : Credential { >> this(....) { >> .... >> } >> >> string encode(....) { >> >> } >> >> private: >> .... >> } >> >> >> TypeTuple!(string, string) AWSKeys() { >> import std.process; >> return tuple(environment.get("AWS_ACCESS_KEY"), >> environment.get("AWS_SECRET_KEY")); >> } > > Yes you guessed good, i don't have any experience with OOP (i have some > experience with C - simple AVR projects and tons of bash scripts) this > is my first such kind of language which I'm trying to learn. For > beginning I'm trying to avoid advanced things like templates or from > your example touples (Touples looks for me like some kind of array but > every cell can be different type, am i right? Eg tuple from your example > is that same what string[2] var?) i was reading about it but for now i > can't understand what they are and for what they are useful. Templates are just compile time arguments :) Mostly used for types and constants. Simple concept, just don't get too scared off by what is possible with template if's. Tuples are pretty simple. It's basically just a struct. They are not arrays. But they do have a similar behavior. With opIndex overloading. You could for example use: struct AWSKeys { string access, secret; static AWSKeys get() { import std.process : environment; return AWSKeys(environment.get("AWS_ACCESS_KEY"), environment.get("AWS_SECRET_KEY")); } } Instead of that free function and tuples. > I'm trying to learn on the examples and honestly i'm not understand how > that TypeTuple is resolving my problem with default values for classes? It wasn't meant to, I got started rewriting the example code you gave, and ehh gave up after the basics of the class/interface. > Second thing that interfaces, are they needed? Without it you can write > same function just compilator wont be screaming for it lack. An interface basically says, this object adheres to these methods. When dealing with possibly changing authentication/communication protocols you would have the interface being how you get what to send, but the actual implementation being whatever you want to be using. Keep in mind, this class which handles creating the messages to the remote api's is not per message sent. It is a global communication mechanism. If you didn't need to make it easily changeable I would say not even bother with OOP at all. I would recommend coming on to #d on Freenode, we can help you better there. |
October 12, 2015 Re: Class, constructor and inherance. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Rikki Cattermole | On Monday, 12 October 2015 at 03:29:12 UTC, Rikki Cattermole wrote:
> On 12/10/15 4:13 PM, holo wrote:
>>>
>>> By the looks, I'm guessing you do not have much experience when it
>>> comes to OOP.
>>>
>>> I think you are wanting something a bit closer to:
>>>
>>> import std.typecons : tuple, TypeTuple;
>>>
>>> interface Credential {
>>> string encode(....);
>>> }
>>>
>>> class SigV4 : Credential {
>>> this(....) {
>>> ....
>>> }
>>>
>>> string encode(....) {
>>>
>>> }
>>>
>>> private:
>>> ....
>>> }
>>>
>>>
>>> TypeTuple!(string, string) AWSKeys() {
>>> import std.process;
>>> return tuple(environment.get("AWS_ACCESS_KEY"),
>>> environment.get("AWS_SECRET_KEY"));
>>> }
>>
>> Yes you guessed good, i don't have any experience with OOP (i have some
>> experience with C - simple AVR projects and tons of bash scripts) this
>> is my first such kind of language which I'm trying to learn. For
>> beginning I'm trying to avoid advanced things like templates or from
>> your example touples (Touples looks for me like some kind of array but
>> every cell can be different type, am i right? Eg tuple from your example
>> is that same what string[2] var?) i was reading about it but for now i
>> can't understand what they are and for what they are useful.
>
> Templates are just compile time arguments :) Mostly used for types and constants.
> Simple concept, just don't get too scared off by what is possible with template if's.
>
> Tuples are pretty simple. It's basically just a struct. They are not arrays. But they do have a similar behavior. With opIndex overloading.
> You could for example use:
>
> struct AWSKeys {
> string access, secret;
>
> static AWSKeys get() {
> import std.process : environment;
> return AWSKeys(environment.get("AWS_ACCESS_KEY"), environment.get("AWS_SECRET_KEY"));
> }
> }
>
> Instead of that free function and tuples.
>
>> I'm trying to learn on the examples and honestly i'm not understand how
>> that TypeTuple is resolving my problem with default values for classes?
>
> It wasn't meant to, I got started rewriting the example code you gave, and ehh gave up after the basics of the class/interface.
>
>> Second thing that interfaces, are they needed? Without it you can write
>> same function just compilator wont be screaming for it lack.
>
> An interface basically says, this object adheres to these methods.
> When dealing with possibly changing authentication/communication protocols you would have the interface being how you get what to send, but the actual implementation being whatever you want to be using.
>
> Keep in mind, this class which handles creating the messages to the remote api's is not per message sent. It is a global communication mechanism. If you didn't need to make it easily changeable I would say not even bother with OOP at all.
>
> I would recommend coming on to #d on Freenode, we can help you better there.
Thank you for explanation tomorrow (today) will back to it and read it carefully, will join IRC too. //almost 6:00AM here :)
|
October 12, 2015 Re: Class, constructor and inherance. | ||||
---|---|---|---|---|
| ||||
Posted in reply to holo | On 10/11/2015 08:26 PM, holo wrote: > On Monday, 12 October 2015 at 02:30:43 UTC, Meta wrote: >> On Monday, 12 October 2015 at 02:14:35 UTC, holo wrote: >>> class credential >>> { >>> auto accessKey = environment.get["AWS_ACCESS_KEY"]; >>> auto secretKey = environment.get["AWS_SECRET_KEY"]; >>> } >>> >>> class sigv4 : credential >>> { >>> private: >>> const algorithm = "AWS4-HMAC-SHA256"; >>> >>> auto currentClock = Clock.currTime(UTC()); >>> auto currentDate = cast(Date)currentClock; >>> auto curDateStr = currentDate.toISOString; >>> auto currentTime = cast(TimeOfDay)currentClock; >>> auto curTimeStr = currentTime.toISOString; >>> auto xamztime = curDateStr ~ "T" ~ curTimeStr ~ "Z"; >>> } >> >> You should set these in the constructor rather than in the class body >> (the only one that's okay to intialize here is `algorithm`, as it's a >> const string). > > I rewrite it to something like this: What Meta is saying is that the expressions used for default values class bodies must be known at compile time. For example, you cannot get current time at run time. Besides, if it did work, there is the question of "should every sigv4 object get the same default value currentClock, or should every object get their own time?" > class credential > { > auto accessKey = environment.get["AWS_ACCESS_KEY"]; > auto secretKey = environment.get["AWS_SECRET_KEY"]; > } As mentioned, that cannot compile. > class sigv4 : credential > { > this(string URI = "/", string queryStr = > "Action=DescribeInstances&Version=2013-10-15", string headerStr = > "host:" ~ host ~ "\n" ~ "x-amz-date:" ~ xamztime ~ "\n", string headers > = "host;x-amz-date") > { > auto currentClock = Clock.currTime(UTC()); That is a known error, which is usually caused by copy-paste: Because you used 'auot' on the left-hand side, that is the definition of a local variable. 'currentClock' above is not the member of this class. It is adviced to use fully qualify members with this. in constructors: this.currentClock = // ... > auto currentClock = Clock.currTime(UTC()); Just define the members without a default value; they will be initialized in the constructor: SysTime currentDate; > My question was too if now i will inherit that class, will that default > values be in child class available? Yes, every variable will obey its default value. When in doubt, test with simple examples. :) class Base { int i = 42; } class Derived : Base { int j; this() { this.j = 100; } } void main() { auto d = new Derived(); assert(d.i == 42); // set by default value assert(d.j == 100); // set in the constructor } Ali |
October 12, 2015 Re: Class, constructor and inherance. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Monday 12 October 2015 07:28, Ali Çehreli wrote:
> For example, you cannot get current time at run time.
I think you mean compile time here.
|
October 12, 2015 Re: Class, constructor and inherance. | ||||
---|---|---|---|---|
| ||||
Posted in reply to anonymous | On 10/11/2015 10:35 PM, anonymous wrote:
> On Monday 12 October 2015 07:28, Ali Çehreli wrote:
>
>> For example, you cannot get current time at run time.
>
> I think you mean compile time here.
>
Thanks. :)
Ali
|
Copyright © 1999-2021 by the D Language Foundation