From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,174ec7dc941a1068 X-Google-Attributes: gid103376,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!postnews.google.com!k79g2000hse.googlegroups.com!not-for-mail From: Matthew Heaney Newsgroups: comp.lang.ada Subject: Re: Factory Pattern Date: Wed, 25 Jul 2007 12:27:59 -0700 Organization: http://groups.google.com Message-ID: <1185391679.375281.277550@k79g2000hse.googlegroups.com> References: <1185387571.367570.163160@r34g2000hsd.googlegroups.com> NNTP-Posting-Host: 66.162.65.129 Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" X-Trace: posting.google.com 1185391679 17730 127.0.0.1 (25 Jul 2007 19:27:59 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Wed, 25 Jul 2007 19:27:59 +0000 (UTC) In-Reply-To: <1185387571.367570.163160@r34g2000hsd.googlegroups.com> User-Agent: G2/1.0 X-HTTP-UserAgent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.5) Gecko/20070713 Firefox/2.0.0.5,gzip(gfe),gzip(gfe) Complaints-To: groups-abuse@google.com Injection-Info: k79g2000hse.googlegroups.com; posting-host=66.162.65.129; posting-account=ps2QrAMAAAA6_jCuRt2JEIpn5Otqf_w0 Xref: g2news2.google.com comp.lang.ada:1184 Date: 2007-07-25T12:27:59-07:00 List-Id: On Jul 25, 2:19 pm, shaunpatter...@gmail.com wrote: > > My code looks something like this: > > type Message is abstract tagged; You need to say more here, but see below. > type Message_Class is access all Message'Class; In Ada05 you might not need this access type, since functions can now return an anonymous access value. Also, if you want to force clients of your abstraction to call your constructor, you should probably declare the type as limited: type Message is abstract tagged limited null record; If your root type has payload that you want to make private, then you can say: type Message is abstract tagged limited private; ... private type Message is abstract tagged limited record ... end record; > derived type: > > package MessageInteger_Pkg is You probably want to declare the partial view of your type in the public part, and with an unknown discriminant: type MessageInteger (<>) is new Message with private; > > -- I want this to act like a constructor > -- Just fills in the value > function create (i : Integer) return MessageInteger; > > private > type MessageInteger with new Message with > record > value : Integer; > end record; > > end MessageInteger_Pkg; > > -- create looks like this: > function create (i : Integer) return MessageInteger is > msg : MessageInteger; > begin > msg.value := i; > return msg; > end create; This won't work if the type is limited. You can say either: function Create (I : Integer) return MessageInteger is begin return (Value => I); end; or function Create (I : Integer) return MessageInteger is begin return Result : MessageInteger do Result.Value := I; end return; end Create; > Factory method: > > -- I would like it to work like this... > function createMessage (type : Integer) return Message_Class is > begin > case type is > when 0 => > return MessageInteger_Pkg.create (1234); > when others => > return MessageSomethingElse_Pkg.create > ("blah"); > end case > > end createMessage You can do this: function CreateMessage (T : Integer) return Message'Class is begin case T is when 0 => return MessageInteger_Pkg.Create (T); when others => return MessageSomethingElse_Pkg.Create; end case; end CreateMessage; This avoids any use of pointers. This might or might not be what you need. Another possibility is: function CreateMessage (T : Integer) return not null access Message'Class is begin case T is when 0 => return MessageInteger_Pkg.Create (T); when others => return MessageSomethingElse_Pkg.Create; end case; end CreateMessage; (You'll have to also change the ctors for each derived type to return an access value designating the specific type.) > However - it doesn't like me returning the MessageInteger from a > class > that returns a Message_Class (obviously..) Right, because (in your original example) MessageInteger_Pkg.Create returns a value of the type, while CreateMessage returns an access value. > Now if I do this -- changing the constructor to take in a > Message_Class.... > > function createMessage (type : Integer) return Message_Class is > decodedMessage : Message_Class; > begin > case type is > when 0 => > decodedMessage := new > MessageInteger_Pkg.MessageInteger; > MessageInteger_Pkg.create (decodedMessage, > 1234); -- change the decoded message this way > return decodedMessage; > when others => > return MessageSomethingElse_Pkg.create > ("blah"); > end case > > end createMessage > > -- That method works... but I find the intermediary step of making a > new object decodedMessage > to someone unneeded? There must be another way of doing this. > Perhaps I should move the "new" > to the create function? Yes, move the new to the Create function for each derived type. (There are others ways of solving this problem, but that will at least get you going.) > And... I'm not completely sure I'm doing all this correctly in Ada. > LIke I said, I'm very new to > Ada. That's OK. That's what CLA is for. Welcome! -Matt