こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

booleanのエラーコードーの意味が分かりません

三角形を作るコードを書きました、JAVAの超初心者です宜しくお願いします。

下記のエラーコードが出ています。

1.「型Mathのメソッドabs(int)は引数(boolean)に適用できません。」
ここでどうしてもbooleanで答えを表示させたい場合には、どこをどのように書き直せばよいのでしょうか。
このような書き方がエラーであれば全てのbooleanコードーがエラーになってしまうような気がするのですが。

2.これをEclipseで実行させた場合には、args[1]~args[2]のデーター入力はどのようにしてやるのでしょうか。
実行させたときにキーから入力してやるのですか。

3. コンスタラクタ「this.L1 = a ;」でわざわざ「L1=a;」を定義してやる意味が良く分かりません。
他のメッソド「boolean isTriangle()」、「double getArea()」は「L1・・」で定義されている関数なのにわざわざ「L1=a;」を定義してやる意味が理解できません。
このケースではたまたまコンストラクタは必要ないし、省略も可かもしれませんが。
メッソドの後ろの「()」は、必要の場合はメッソドの引数を入れると本には書いていますが、クラス内で、メンバー変数として(この場合は「int L1, L2, L3 ;」)定義してやれば、メッソドからは、アクセスできるのでそのような処理がなぜ必要かがわかりません。

以上宜しくお願い致します。
________________________________
class Sample {
int L1, L2, L3 ;
Sample (int a, int b, int c) {
this.L1 = a ;
this.L2 = b ;
this.L3 = c ;
}
boolean isTriangle() {
if(( L1 + L2 ) > L3 && Math.abs(( L1 - L2 ) < L3 )) {
boolean S_bool = true ;
    }
else{
boolean S_bool = false ;
}
return S_bool ;
}
double getArea() {
double S = (double)((L1+L2+L3)/2.0) ;
double area = Math.sqrt(S*(S-L1)*(S-L2)*(S-L3));
return area ;
}
}

class Sample_Test {
public static void main(String args[]) {
int s1 = Integer.parseInt( args[ 0 ] ) ;
int s2 = Integer.parseInt( args[ 1 ] ) ;
int s3 = Integer.parseInt( args[ 2 ] ) ;
Sanmple t1 = new Sample ( s1 , s2 , s3 ) ;
boolean sankaku = t1.isTriangle() ;
double menseki = t1.getArea() ;
System.out.println( sankaku ) ;
System.out.println( menseki ) ;
}
}

投稿日時 - 2007-08-02 09:19:25

QNo.3220353

すぐに回答ほしいです

質問者が選んだベストアンサー

補足であった1.2.についてですが、これはhtgoさんの考えの通りです。
今回のコードでは、コンストラクタでクラス変数L1…に初期値を設定しています。
そして、isTriangle()、getArea()メソッドがその値を参照し、各処理を行っています。

3.についてですが、クラス変数について言えば、特に何も指定せず、
質問のコードのまま引数なしで問題ないです。

クラス変数はどこかで値を代入しないと意味がない、というのは前回の回答から
繰り返し言ってるわけですが、「どこで代入するか」についてはそのクラスによります。
というか、そのクラスを書く段階で(もっと言えばクラスを設計する時に)
クラスを作る人(設計書を書く人)が決めるものです。

質問のコードではSampleクラスを作るときに、クラス変数の代入はコンストラクタで行う
ということにしているわけです。
他の作り方としては、コンストラクタは特に指定せず(デフォルトコンストラクタのままで)
値を設定する専用のメソッドsetSides(int a, int b, int c){…}を作る、
という方法もあります。

ここで、「わざわざメソッドを用意しなくても、isTriangle()やgetArea()に
引数を指定すればいいじゃないか」と思うかもしれません。
確かに、それでもコードはできますが、外部から呼び出されるメソッドが2つあるので、
引数は両方に指定しないといけなくなり、不便です。
なので、値の設定は専用のメソッドで行う方が好ましいです。

ちょっと話がそれました。
クラス変数を、「コンストラクタで初期化する」か、「専用のメソッドで初期化する」か
という話でしたが、これはどう使い分けるといいでしょうか。
これは、それぞれのやり方の特徴を理解すると分かりやすいです。

コンストラクタは、Sanmple t1 = new Sample ( s1 , s2 , s3 ) ;
のような所で呼び出されます。
t1を使う時初めに必ず呼び出され、それっきり呼び出されません。
つまり、最初に呼び出されるので、クラス変数には必ず値が入っていることになります。
一方、一度呼び出されると、以降は呼び出されないので、値を再代入できません。

専用のメソッドを使うとどうでしょうか。
この場合、isTriangle()やgetArea()を呼び出す前に専用メソッドを実行していないと
値の代入漏れが発生してしまいます。
ただし、コンストラクタではないので、何度でも呼び出しができ、値を代入し直せます。

例えばSampleクラスが、「画面にランダムなサイズの三角形をたくさん表示し、
それぞれの面積を表示しておく」という用途に使うとします。(例え悪いなあ。どんなプログラムやねん)
この場合、個々の三角形は、値を1回しか代入しないですし、面積の表示も1回だけです。
なので、コンストラクタで値を代入させるようにすればいいですね。
Sanmple t1 = new Sample ( 3 , 4 , 5 ) ;
double area1 = t1.getArea();
Sanmple t2 = new Sample ( 6 , 7 , 8 ) ;
double area2 = t2.getArea();
 :

また、Sampleクラスが、「三辺を入力すると、その面積を返す計算機」に使うとします。
すると、計算は何回もするので、値を代入し直せた方がいいですね。
なので、専用メソッドを使って値を代入しなおせるようにします。

このように、クラス変数を初期化する方法はいろいろあり、用途もさまざまです。
今回の例のような考え方が全てではないですが、何かの参考になればと思います。

投稿日時 - 2007-08-08 01:56:40

お礼

neko_nokoさん、有難う御座います。
プログラム流れが良く分かりました。
これを期にもっと勉強してみます。

投稿日時 - 2007-08-08 16:44:27

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(5)

ANo.4

#2です。こんばんは。

たぶん、勉強し始めでいろんな疑問がそれぞれ結びついていないのだと思います。
Java以外の言語経験がおありかどうか分からないのでもしかしたら失礼なことを書いているかもしれませんが、ちょっと長文で書いてみました。


>1. まず「コンストラクタ」は「初期値を代入するために「int a・・」を
>仮引数として定義、「コンストラクタ内」で「L1にa・・」を代入して、初期値を
>設定している。」との理解で良いのでしょうか。

よいと思います。ただ質問文を見ていると、「L1」とか「a」ではなく具体的な値を意識して考えた方が分かりやすいのではないでしょうか?例えば、

Sample s1 = new Sample(10,10,15);

により、Sampleクラスの新しいインスタンスs1が作成されます。
このときSampleのコンストラクタSample(int a, int b, int c)が呼ばれ、
インスタンスs1のメンバーであるL1,L2,L3にはそれぞれ10,10,15という具体的な値が
this.L1 = a;
this.L2 = b;
this.L3 = c;
の処理により代入されます。

さらに続けて
Sample s2 = new Sample(5,5,8);
と書けば、s2のL1,L2,L3はそれぞれ5,5,8です。ここでs1とs2のL1,L2,L3は別のものですが、それはよいですよね?

初期値をセットするためにコンストラクタが必ず引数を持つ必要があるわけではなく、デフォルトコンストラクタのみを持ち、これとは別にsetterメソッドを定義することもあるでしょう。
例)
class Sample{
private int L1;
private int L2;
private int L3;
public void setL1(int a){
this.L1 = a;
}
public void setL2(
:

Sample s1 = new Sample();
s1.setL1(10);
s1.setL2(10);
s1.setL3(15);

ただ、ご提示のコードでは、Sampleクラスのインスタンスを作成する場合には、常にL1,L2,L3の値をセットするのでしょうから、いちいち3行で書くよりも、引数ありのコンストラクタを用意しておくことによって、インスタンス作成と初期値のセットを一行で書ける、というだけのことです。
あとは、インスタンス生成時にしか値をセットできず、その後は変更できないようにする効果もありますが。


>2. boolean isTriangle( ){ }、doble getAnget( ){ }は、「L1・・」で
>構成されるメッドである。
>その値(L1・・)は、「int L1・・」により、メンバー(クラス)変数として宣言(定
>義)されている」のだから、各メソッドから「参照(?)」は可能である。

isTriangle()やgetArea()からL1やL2にアクセスできるのはその通りです。
アクセスできるかどうかと、どうやってL1やL2に値をセットするかは全然別の話です。
提示されたテストコードからコンストラクタを外した場合、下記の

Sanmple t1 = new Sample ( s1 , s2 , s3 ) ;
boolean sankaku = t1.isTriangle() ;

という箇所は

Sanmple t1 = new Sample () ;
boolean sankaku = t1.isTriangle() ;

となるかと思います。
この場合、SampleクラスのL1やL3はただ宣言しただけですので、そこに10とか15とかの値は入っていません。isTriangle()からアクセスしたL1やL2は初期化されないまま(ここではintなのでゼロ)でしょう。

ちなみに、

>処理をする度に、メンバー変数にその処理結果が返される

と書かれていますが、ご提示のコードでisTriangle()やisArea()はL1やL2を見ていますがその値を変えているわけではないので、この表現はおかしいです。

>3. となると、boolean isTriangle( )、doble getAnget( )の( )には、
>何を入れてやるのでしょうか

このケースでは別に不要ではないでしょうか。

投稿日時 - 2007-08-08 01:35:55

お礼

kztkさん、有難う御座います。
プログラムの流れが良く分かりました。
オブジェクト指向型のプログラムは初めてなので、全体の流れがもう一つ掴みきれません。まして複数のクラスがあると。
もう少し基本のところと多く書くことが必要ですね。
痛感します。
何でここでつまずいているのかよく考えたところ、
多分BASICなどでは、サブルーチン内はサブルーチンのみの(ローカル)変数が自由に使え、メインプログラム(の変数)とは引数でのやりとりするシステムになっていますよネ。
JAVAの場合は逆に、メソッド内ではメインプログラムのクラス変数にアクセスできるような書き方になっているのではないでしょうか。
(勿論プログラムの作リ方にもよるのでしょうが)
オブジェクトの持つ情報の受け渡しを考えると、このようなシステムが多分良いのでしょうが、いづれにしても多くコードを書き慣れるしかないと思います。有難う御座いました。

投稿日時 - 2007-08-08 16:41:35

ANo.3

>メンバー変数として宣言しているので、他のメソッドからアクセス(変数値を見ること
>が可能)できるという意味です。

同じクラスのメソッドなら「見ること」は可能です。
ただ、変数は初期化しないと値が入ってないので、どこかで代入しないといけません。
今回のコードは、それを「コンストラクタでやっている」ということです。

疑問としては、「なぜコンストラクタで代入する必要があるのか?」
ということでよかったでしょうか。
※それなら、「どこで値を代入しておく必要があるか」ということになります。


>処理をする度に、メンバー変数にその処理結果が返される訳で、次のメソッドはその処
>理結果後の値から次の処理を行っていけば良いのでは

ここの部分が良く分からなかったので、逆に質問します。
「処理をする度に」というのは、isTriangle()メソッドの処理でしょうか、
それとも、this.L1 = a ;のようなメンバー変数への代入処理でしょうか?
文面からすると後者かな、という気がします。
その場合、質問は「コンストラクタで値を代入するのではなく、
別の所で値を代入してもよいのではないか」ということになりますが、
そういうことでしょうか?

投稿日時 - 2007-08-07 01:35:02

補足

neko_nokoさん、有難う御座います。
今までの皆さんからの回答なり、その後の私の勉強を含めると、私の質問自体の何が疑問なのかを明確に皆さんに理解して頂いてないということになるのでしょうね。

改めて質問を整理してみました。その後自分なりに色々と他の本を読んだりしたので、多分最初とは違った内容になっていると思いますが。

1.まず「コンストラクタ」は「初期値を代入するために「int a・・」を仮引数として定義、「コンストラクタ内」で「L1にa・・」を代入して、初期値を設定している。」との理解で良いのでしょうか。

2.boolean isTriangle( ){ }、doble getAnget( ){ }は、「L1・・」で構成されるメ
  ッドである。
その値(L1・・)は、「int L1・・」により、メンバー(クラス)変数として宣言(定
義)されている」のだから、各メソッドから「参照(?)」は可能である。

という事で良いのでしょうか。

3.となると、boolean isTriangle( )、doble getAnget( )の( )には、何を入れてや
るのでしょうか

以上、宜しくお願いします。

投稿日時 - 2007-08-07 09:21:43

ANo.2

質問3のみについて、まず質問の意味を正確に理解させてください。

>他のメッソド「boolean isTriangle()」、「double getArea()」は「L1・・」
>で定義されている関数なのに

ここの意味が理解できません。
「「L1・・」で定義されている関数」というのは、どういう意味でしょうか?

>わざわざ「L1=a;」を定義してやる意味が理解できません。
>このケースではたまたまコンストラクタは必要ないし、省略も可かもしれませんが。

これは、コンストラクタの

this.L1 = a ;
this.L2 = b ;
this.L3 = c ;

3行が不要、つまり

Sample (int a, int b, int c) {
}

でよいという意味でしょうか、それともコンストラクタ自体不要という
意味でしょうか?あるいは、

>メッソドの後ろの「()」は、必要の場合はメッソドの引数を入れると
>本には書いていますが、

ここでいう「メソッド」はSampleクラスのコンストラクタのことを
指していますか?つまり、Sampleクラスのコンストラクタ

Sample (int a, int b, int c)

に、引数がついていることに疑問を持たれている?

>クラス内で、メンバー変数として(この場合は「int L1, L2, L3 ;」)
>定義してやれば、メッソドからは、アクセスできるので

ここでいう「メッソドからは、アクセスできる」というのは、
コンストラクタ内で
this.L1 = a ;
this.L2 = b ;
this.L3 = c ;
としなくても、他のメソッド(例えばgetArea())ではL1,L2,L3にアクセス
できるという意味ですか?

>そのような処理がなぜ必要かがわかりません。

繰り返しですが、「そのような処理」とは

this.L1 = a ;
this.L2 = b ;
this.L3 = c ;

のことでよいですか?

投稿日時 - 2007-08-02 14:08:01

補足

 kztkさん、回答有難うございます、私自身は本を読みながら理解出来ていないなりで質問している部分もありますので、内容に間違いがありましたら、ご指摘願います。
 ただ、私の疑問とするところと頂いた質問なり、疑問点に対する私の考え、解釈は以下の通りです。
 回答をお待ちしています。

>他のメッソド「boolean isTriangle()」、「double getArea()」は「L1・・」で定義されている関数なのに

⇒ 「boolean isTriangle()」、「double getArea()」の内容は、「L1・・」のみの変数で書かれており、何故、コンストラクタで「this.a」の代入行為が必要になるのかという意味です。
(実は、コンストラクタを定義する意味(コンストラクタを書いてやることと値を代入してやること(初期値を設定する意味は「コンストラクタを書いたついでに初期値を設定する程度の意味しかない」と聞きましたが))が良く理解できていません。

>このケースではたまたまコンストラクタは必要ないし、省略も可かもしれませんが。

⇒ この意味は、デフォルトでコンストラクタが設定されるのでここでは「特にコンストラクタ自体を書く必要がない」という意味です。

>ここでいう「メッソドからは、アクセスできる」というのは、
コンストラクタ内で
this.L1 = a ;
this.L2 = b ;
this.L3 = c ;
としなくても、他のメソッド(例えばgetArea())ではL1,L2,L3にアクセスできるという意味ですか?

⇒ そうです、
class Sample {
int L1, L2, L3 ;  でメンバー変数として宣言しているので、他のメソッドからアクセス(変数値を見ることが可能)できるという意味です。
ということになると、わたしの疑問では、このような形(書式)でメンバー変数を置いてやると、必ず他のメソッドからアクセス可能な訳でメソッドの直ぐ後ろに書いている()で引数を定義してやらなくても、
処理をする度に、メンバー変数にその処理結果が返される訳で、次のメソッドはその処理結果後の値から次の処理を行っていけば良いのでは
との疑問です。

投稿日時 - 2007-08-02 17:57:39

ANo.1

Ans.1
 absメソッドに渡す引数は、「絶対値を取得する関数に渡す値」なので、
 出力は関係ありません。
 数学の知識が不足しているような気がします。
 絶対値関数とは「-3の絶対値は3」のような値を求める為の関数ですから、
 true/falseの絶対値なんてありえないわけです。
 このコーディングからは、何がしたいのか良くわからないので、
 修正も難しいのですが、「L1とL2の差がL3より小さい」事を求めたいのなら
 「Math.abs(L1-L2) < L3」
 です。
Ans.2 Eclipseのデバッグ(虫の絵)から「構成及びデバッグ」を選択して
 (x)=引数 の所で設定します。

Ans.3 これは、定義ではありません。「代入」です。
 Sampleクラスのメンバ変数に引数として渡された値を代入しているのです。
 省略してしまうと、int型の場合0がL1~L3に入ったまま初期値が変更されない事になります。
 今回の質問の内容だと毎回引数で渡してもいいかもしれませんが、
 「ファイルのオープン」などの処理は1回しかしませんが、
 「ファイルに1行データを書く」という処理は何度も実施されますよね。
 そのとき、毎回引数にファイル名を渡して「オープン」「クローズ」するのはおかしいので、
 「ファイルオープン」した時のファイル情報はクラスに1個だけ持っていて、
 「1行データを書く」という時はオープンされた情報を使う・・・という事をするのです。

投稿日時 - 2007-08-02 10:12:57

あなたにオススメの質問