複数のユニットを使用するには?


  2005-05-28 05:30:03  No: 15129

はじめまして!!今学校でDelphiをならっているんですけど、わからない事が
あって質問します。複数のユニットで値をやりとりするのですが、その際に、
グローバル変数を使いたくありません。他にどこに他のユニット名を定義したら
よろしいのでしょうか?お願いします!!!!


りおりお  2005-05-28 08:21:09  No: 15130

他のユニットから見えるのは interface 部だけです。

で、ヘルプに依れば

「インターフェース部は,クライアントが使用できる定数,型,変数,手続き,および関数を宣言します。」

とあります。

> グローバル変数を使いたくありません。

ということであれば、関数に隠蔽するしかないように思います。クラス宣言の無いユニットもありますし。あっても、必ずしもインスタンスが作られるともかぎりませんし。


  2005-05-30 20:49:24  No: 15131

>関数に隠蔽するしかないように思います。クラス宣言の無いユニットもあります
>し。あっても、必ずしもインスタンスが作られるともかぎりませんし

とはどういう事ですか?


Sayke  2005-05-30 23:19:39  No: 15132

グローバル変数を使用したくないなら関数や手続きで
値のやり取りをしないといけませんね。

Form1からForm2に値を渡したいのなら
Form2は
    Privateに
      IntData :Integer;
    Publicに
     Procedure SetIntData(i :Integer);
ほんで
    procedure TForm2.SetIntData(i :Integer);
    begin
      IntData := i;
    end;

Form1は
    implementation  節に
      Form2をUsesして
      (ファイルからユニットを使うで選択したら自動で入ります)

    procedure TFrom1.Button1OnClick(Sender :TObject);
    begin
       From2.SetData(100);
    end;
などとすば、如何でしょうか。


Sayke  2005-05-31 02:56:51  No: 15133

>implementation  節に
>Form2をUsesして
>(ファイルからユニットを使うで選択したら自動で入ります)

う〜む。わかりづらかったとゆうより、表現が・・・です。
デフォルトのままなら
implementation  節に
Uses Unit2;
(ファイルからユニットを使うで選択したら自動で入ります)
ですね。

それから、
>クラス宣言の無いユニットもあります
例えば、ファイル→新規作成→ユニットで表示されるユニットファイルには
クラス宣言がありません。
各ユニットやプロジェクトで共通で使用する関数・手続きなどを
単に記述して使用するなら、まさにその通りになります。

>あっても、必ずしもインスタンスが作られるともかぎりません
適当にFormを幾つか作ってから、プロジェクトソースを見てください。
Application.CreateForm(・・・・);
の記述が自動で追加されているはずです。
このお陰で、自動的に各フォームのインスタンスが作成され、実行中に
Form1からForm2の関数なりが参照できます。
ですが、プロジェクトソースから
Application.CreateForm(TForm2,From2);
をコメントアウトしてから、実行後参照してみてください。
必ず、エラーになります。(インスタンスが作成されていない為)

また、他の例では通常Formに自動でUsesされるClassesユニットのTStringListは自前でCreateしないと使えません。
(使用したら、破棄することも忘れずに)
Classesのユニットの記述を参照してみてください。

と、いう事かな?(無責任な)
この場合は、あまり関係ないかも。

Delphiを学校でね。個人的には大歓迎です。
頑張ってください。
某Delphi保存委員会長は泣いて喜ぶだろうなぁ。
って、関係ない話題です。


  2005-05-31 04:03:47  No: 15134

フォームをグローバル変数以外で定義することは可能なんですか?
フォームは自動でグローバルになるのでダメだって言われたんです


Syake  2005-05-31 04:18:33  No: 15135

>フォームをグローバル変数以外で定義することは可能なんですか?
え゛っ!
何のこと?
>複数のユニットで値をやりとりするのですが、その際に、
>グローバル変数を使いたくありません。
では無かったの?


  2005-05-31 04:27:32  No: 15136

いえ、いかなるときもグローバルを使いたくないんです。
何か方法はないのですか?


Syake  2005-05-31 04:47:36  No: 15137

で、質問はどっちなの?

>フォームをグローバル変数以外で定義することは可能なんですか?
って事は
interface  節の
var
 Form1 :TForm1;
も嫌だって事になりますが。


ななし  2005-05-31 05:04:13  No: 15138

> いえ、いかなるときもグローバルを使いたくないんです。
か、過激ですね。グローバル=無条件に悪なのでしょうか?
ちょっと理解が足りない気がします。なぜ悪なのか考えましょう。

> 何か方法はないのですか?
DLLの中に閉じ込めてしまえば、他からはアクセスできませんね。


Syake  2005-05-31 05:11:39  No: 15139

>か、過激ですね。
ですね。

>> 何か方法はないのですか?
>DLLの中に閉じ込めてしまえば、他からはアクセスできませんね。
確かに
ですが、アクセスの問題なら単にUsesしなければ良いとも言えます。


  2005-05-31 06:17:06  No: 15140

>interface  節の
>var
> Form1 :TForm1;
>も嫌だって事になりますが

そうなんですよ!!絶対にグローバルはダメダメなんです・・・


ローカル  2005-05-31 06:41:41  No: 15141

> 絶対にグローバルはダメダメなんです・・・
えっ?! そんなの、誰が決めたんですか?
先生?


Syake  2005-05-31 06:50:28  No: 15142

インスタンスの参照もですか?
先生の指導を聞き間違えたとか。
変数のグローバル化は極力しないようには聞きますが
インスタンスの参照までは言わないと思うけど
どうなのでしょうか?


RAN  2005-05-31 07:09:30  No: 15143

> インスタンスの参照までは言わないと思うけど
サブシステムの独立性を高めるために、別のサブシステムのインスタンス
を直接参照させたくない・禁止というような事はよくあります。

といっても、手間がかかります。またシステム上の目的なしに、
グローバル=ダメダメと突っ走るのは無意味です。


Syake  2005-05-31 07:44:16  No: 15144

ふむふむ
言っても仕方ないので

例えば
家族ってクラスがあるとして、氏名ってデータが入るとします。
家族クラスをどこそこの田中家とどこそこの桜家をインスタンス
した場合に、同名があったとしても、どこそこの田中家の隆と、
どこそこの桜家の隆ではは別物だし違うと判断できますよね。

ところがグローバル変数で単に氏名と宣言して隆と入れたら
どこの隆かわかんないし、特定するためなら隆という名前は
唯一無二でなければなりませんよね。
現実無理ですよね。

何となくわかります。わかんないか?(適切な表現ではない)
すいません一杯やってます(投稿スンナよm(__)m)

Fromも同じです。
Editをフォームに追加するのは同じことですがForm1のEdit1と
Form2のEdit1は別物です。
Form2からではForm1.Edit1としなければForm1のEdit1は使用
できません。
でも本来のグローバル変数をIntXを宣言したなら、Form1でも
Form2でもIntXは同じものです。
これを、互いのPublicでIntXを宣言したら、別物です。
Form2はForm1.IntXと、From1はForm2.IntXとしなければ使えません。
これでも十分に隠蔽してると思いますが。
もっとも、こういった方法はあまり使いませんけど

ちなみに
>フォームをグローバル変数以外で定義することは可能なんですか?
私はこれで困ったことや、メンテが困難になるなんて事は経験ありません。
私も経験が浅いので方法があったら聞きたいし、あったとして実務上そうす
る意味があんのかな?


Syake  2005-05-31 07:47:59  No: 15145

あら、投稿してるあいだに返答が・・・
>サブシステムの独立性を高めるために、別のサブシステムのインスタンス
>を直接参照させたくない・禁止というような事はよくあります。
勉強不足です。
どういったことなのか、どうするのかさっぱり見当つきません(^_^;)


RAN  2005-05-31 08:32:48  No: 15146

ちょっと説明しずらいのですが、

Aの中でBを直接呼び出すと、AにはBが必ず必要になってしまう。
でもBではなくCやD・・・といろいろな組み合わせが考えられる。

またA開発部隊がコンパイルする時、B開発部隊からソースを貰って来
ないとコンパイル出来ないのでは困る。

というような話です。


RAN  2005-05-31 08:43:54  No: 15147

> フォームをグローバル変数以外で定義
という話は自分も変な話だと思います。


Syake  2005-05-31 09:08:03  No: 15148

RANさん  ありがとうございます。
>Aの中でBを直接呼び出すと、AにはBが必ず必要になってしまう。
>でもBではなくCやD・・・といろいろな組み合わせが考えられる。
何となくわかる気がします。
その時は気にも留めなかったですが、何かの書籍で似たようなことが
記載してあった記憶がします。

>またA開発部隊がコンパイルする時、B開発部隊からソースを貰って来
>ないとコンパイル出来ないのでは困る。
これは、さずがにその様なプロジェクトの経験がないので、考えた事も
ありませんでした。

今後の為に、学習します。
ありがとうございます。


いたいけなひとみちゃん  2005-05-31 17:47:55  No: 15149

> 愛 2005/05/30(月) 21:17:06
> フォームは自動でグローバルになるのでダメだって言われたんです
「プロジェクトから削除」したら自動生成からはずれます。

自分は、メインフォーム以外、自動生成したフォームを使いません。


  2005-05-31 18:46:16  No: 15150

>フォームをグローバル変数以外で定義
>という話は自分も変な話だと思います。
変な話・・・


ななし  2005-05-31 19:28:04  No: 15151

> 絶対にグローバルはダメダメなんです・・・
どの辺りがダメダメなんですか?


kkk  2005-05-31 19:48:14  No: 15152

> 絶対にグローバルはダメダメなんです・・・
グローバル変数の良し悪しではなくて、たぶん

宿題として
  グローバル変数を使用せずに「チョメチョメ」を作成せよ  
とかがでているのでは?


  2005-05-31 20:03:41  No: 15153

そうです!!kkkさん


りおりお  2005-05-31 20:27:59  No: 15154

ふーむ、で、疑問点は解決できましたか?

課題の意味は分かりましたが、質問者はどこが分からないのか、が分かりません。

個人的には、Delphi のような開発環境では「不自然な課題」だと思います。


  2005-05-31 20:34:24  No: 15155

不自然な課題でも
フォームをグローバルせずに複数のユニットでのデータのやりとりは
可能なんですか?


りおりお  2005-05-31 20:46:50  No: 15156

> フォームをグローバルせずに

まず、Delphi を起動した直後のプロジェクトファイルを見てください。

program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

ここで使われている Form1 は、Unit1.pas で宣言されているグローバル変数です。
これを使わない起動するためには、Unit1 から宣言を削除して

program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

var
  Form1: TForm1;

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

のようにします。プロジェクトファイルの変数は他のユニットから参照できないので
グローバル変数とは違います。(厳密には?ですが。)

> 複数のユニットでのデータのやりとりは可能なんですか?

まず、ユニットファイルと TForm の下位クラスの type 宣言は別の概念です。
これを理解してください。重要です。

で、ここでは簡単にするために、各フォームごとに宣言されたユニットファイル
だけを考えるとします。 Unit1.pas で TForm1 、 Unit2.pas で TForm2 と
いう感じです。そうすると、グローバル変数を使用しないで他ユニットのフォーム
クラスのインスタンスを参照できるか? という問題になります。

わたしは厳密な文法に詳しくないのですが、すぐに思いつきません。いまのところ
は ノー が回答です。


りおりお  2005-05-31 20:51:17  No: 15157

> いまのところは ノー が回答です。

Screen の FormCount と Forms[] を使うと出来るかもしれません。面倒ですが。


ななし  2005-05-31 21:00:49  No: 15158

> 可能なんですか?
学校の課題は自分でやらないと。りおりおさんは優しいなー。
もしかして、うーんと単純な事なんではないかと。

procedure TForm1.Button1Click(Sender: TObject);
var
  Private_Form: TForm2;
begin
  Private_Form := TForm2.Create(nil);
  Private_Form.AIhaArunoka := False;


ななし  2005-05-31 21:08:57  No: 15159

あ、当然、フォーム宣言はグローバルです。

> フォームをグローバルせずに
グローバルなフォームをローカルで生成して

> 複数のユニットでのデータのやりとりは
Form1のユニットとForm2のユニットでデータをやりとりしています。


いたいけなひとみちゃん  2005-05-31 21:21:07  No: 15160

> ななし 2005/05/31(火) 12:00:49
> > 可能なんですか?
> 学校の課題は自分でやらないと。りおりおさんは優しいなー。
まったくです・・・といいつつ、レスつけ。

これなら、いつでもForm2を参照可。

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    Private_Form: TForm2;
  end;

implementation

procedure TForm1.FormCreate(Sender: TObject);
begin
  Private_Form := TForm2.Create(nil{or Self});
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
  Private_Form.Free;
end;

言語的な理解も不足しているから、抽象的すぎて質問が理解不能。
こちらの回答も、同じく理解してもらえない。
こういうとこで、記述方法とか勉強したほうがいいんじゃないのかと思うのだが。
http://santamartadotnet.hp.infoseek.co.jp/documents/delphi/learningdelphi1.html


にしの  2005-05-31 22:48:20  No: 15161

面白そうなので参戦します。

最初にお断り。
私も、ヘルプを見て初めて知ったのですが、
ヘルプの記述「手続きまたは関数の内部で宣言された変数はローカル変数,その他の変数はグローバル変数と呼ばれることがあります。」
ということは、implementation以下にvar 変数:型;としても、グローバル変数ということですよね。
もし、ヘルプの記述通りの「グローバル変数」でしたら、面倒ですよ。動的にメモリを確保し、そのメモリを「グローバル変数を使用しないで」参照できなければなりませんから。
ひとまず、一般的(かどうかはわかりませんが)に、「他のユニットから参照できない変数」=「グローバル変数」ということで書きます。

まず1つめ。Formをグローバル変数を使わずに表示する方法。

//AntiGrobal.dpr(プロジェクトのソース)
program AntiGlobal;

uses
  Forms,
  uMain in 'uMain.pas' {Form1};

{$R *.res}

begin
  ApplicationRun;
end.

//uMain.pas(Form1のソース)
unit uMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

  procedure ApplicationRun;

implementation

{$R *.dfm}

var
  Form1: TForm1;

procedure ApplicationRun;
begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end;

end.

プロジェクト内で行っていた部分をプロシージャにし、uMainのグローバル関数にしてしまう。そのうえで、Form1というグローバル変数を、ユニット変数に変更。
以上でグローバル変数を使わずにFormを表示できますね。

2つめとして、グローバル変数を使わずに他に値を渡す方法。
クラスにプロパティを持たせるのと同じ要領で、ユニットの中に変数を隠蔽すればよいかと思います。

unit uSub;

interface

function GetValue: String;
procedure SetValue(Value: String);

implementation

var
  strValue: String = '';

function GetValue: String;
begin
  Result := strValue;
end;

procedure SetValue(Value: String);
begin
  strValue := Value;
end;

end.


  2005-06-01 02:29:58  No: 15162

もっと素人でもわかるような方法はないんですか?ないならごめんなさい


deldel  2005-06-01 02:33:17  No: 15163

ファイルを介せばグローバル変数は不要ですね。
極めて変ですけど・・・


(# ゜Д゜)  2005-06-01 02:43:37  No: 15164

> もっと素人でもわかるような方法はないんですか?ないならごめんなさい
素人にわかるだって?
あなた、何様ですか?
学校の課題をここで聞いたあげくに、理解できないからわかるような回答しろ?

そんなセリフを出す前に、もっと学習すべきコトがあるでしょう?
本来、学校の課題なんて、こういうとこで聞いて完成させるモノではなく、自分で考えてやるものでしょう。

潔く諦めてください。
少なくとも理解する努力が見えませんので、あなたのような人に理解できる回答は、今後もないでしょう。
# 以下略


ななし  2005-06-01 03:26:12  No: 15165

だいたい答えは出揃っている感じですけど。
どれでもお好きな方法で作成して、提出すれば良いのでは?
正解ではなくても提出点はもらえそうですが。

> もっと素人でもわかるような方法
キーワードは学校。先生。職員室。クラスメート


ふむ…  2005-06-01 03:36:35  No: 15166

典型的な質問の小出しですね。
質問者の質問だけから答えを出そうとすると否応にも回答は難解になりますし、宿題自体が質問者のレベル不相応な悪題に感じ取れます。
質問者自身が先生の問題を理解できていないのであれば、一字一句残さず丸々質問文を紹介してもらえないとこれ以上の回答は不可能ではないでしょうか?


Syake  2005-06-01 07:50:47  No: 15167

何時のまにやら、内容が過激に
質問者の方には悪いですが、別の意味で勉強になります。

まあ、何事にしてもそうですがある程度は自分で勉強して
それでも壁にぶつかったら・・・・
(もっとも、壁は人によって高さが違いますけど)

でもよい時代だなぁと思います。
こうして、顔も名前もわからない方々から親切に色々手助け
をいただけるのですから。
これがなかったら、私自身もは今頃・・・・
ですが、それに甘えないように頑張りたいと思います。


通りすがりV2  2005-06-01 10:35:49  No: 15168

こうやってインターネットが普及した今、どこの誰ともわからない相手に質問して答えてもらえるなんてうらやましい時代になったものです(^^ゞ
自分の時代は、一部のできる学生(こっちが一方的に知っているていどの相手)に友達経由でみせてもらったり、さっぱりわからない仲間をあつめて、課題に取り組んだけど、結局ゲーム大会になってしまい、結局できなかったり、今となってはなつかしい思い出です。
それがなんの因果でプログラマーやっているのやら( ´−`)

さてさて、今回の件ですが・・・
まぁ、悪く言えば、単位さえとれればいい学生なんだから、コピーさせてもらえる知り合いがいないのなら、問題の丸投げでもしてみればいいんです。
(ただし、学生の課題を丸投げを容認しているわけではありません。)

100%の回答ではなく、どういった記述が必要かというものは返ってくるでしょう。
質問者はDelphiはもとより、プログラムの基礎も知らないと思われます。
そういった相手に、いくら素敵なプログラムを見せても、課題の解答じゃないため、何をどう扱えばいいのかわかりません(たぶん)

まず、プログラムを作成するため(課題完成)の方針決めとして、課題全文の提出を希望します。
そうじゃないと、いくらいろいろ回答もらっても、扱い方がわからないのでしょう?  >愛さん

もう一つ思うことは、こういうとこで、質問の仕方も学んできて欲しいと思ったりする
http://www.hyuki.com/writing/techask.html
http://www.geocities.co.jp/SiliconValley/5656/

と、紹介しても、読みそうなのは、回答する側の人ばっかりだったりして(笑)


通りすがりV2  2005-06-01 10:42:10  No: 15169

> まあ、何事にしてもそうですがある程度は自分で勉強して
> それでも壁にぶつかったら・・・・
こういうとこで愚痴るのはあれなんだけど、壁にぶつかって質問してくるのはいいけど、せっかく教えても、しばらくしたらまた同じようなこと質問する人っているよね?
そういうのって、どう教えたらいいのか悩んでしまう。
教えたことをすぐ忘れるような回答の仕方をしている自分が悪いのか、覚えてくれない相手が悪いのか。
|\(ーー;)


HOta  2005-06-01 16:27:59  No: 15170

壁にぶつからずに、すぐに質問するので、すぐに忘れるのでしょう。


sakiyama  2005-06-01 18:20:06  No: 15171

話が変な方向にいってるので、おまけ
usesに追加せず参照する方法。
--unit2.pas

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm2 = class(TForm)
  private
    { Private 宣言 }
    FHoge: Integer; 
  public
    { Public 宣言 }
  published
    property Hoge: Integer read FHoge write FHoge;
  end;

implementation
{$R *.dfm}
initialization
  RegisterClass(TForm2);
end.

-- unit1.pas 
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, TypInfo;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
    FForm2: TForm;
  public
    { Public 宣言 }
  end;

implementation

{$R *.dfm}
var
  localForm: TForm1;
  
procedure TForm1.Button1Click(Sender: TObject);
var
  PropInfo: PPropInfo;
  i: Integer;
begin
  if FForm2 = nil then begin 
    FForm2 := TForm(GetClass('TForm2').NewInstance);
    FForm2.Create(Self);
    FForm2.Show;
  end;
  PropInfo := GetPropInfo(FForm2, 'Hoge');
  if PropInfo = nil then Exit;
  i := GetOrdProp(FForm2, PropInfo);
  SetOrdProp(FForm2, PropInfo, i+1);
  ShowMessage(IntToStr(GetOrdProp(FForm2, PropInfo)));
end;

initialization
  Application.Initialize;
  Application.CreateForm(TForm1, localForm);
  Application.Run;
end.
 
-- project1.dpr

program Project1;

uses
  Forms,
  Unit2 in 'Unit2.pas' {Form2},
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
end.


ニセ愛  2005-06-01 20:02:21  No: 15172

だから素人でもわかる方法を教えてください(藁


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加