Java ワンポイント ~コンソールをリフレッシュする~

イントロダクション

テキストRPGを作成中です。
コンソールのみで展開する仕様なので、コンソールのれふれっふ処理が必要になりました。

調べたので、アップしておきます。

Javaからコマンドを実行する

具体的には、コンソール画面(コマンドプロンプト(Win)やターミナル(Mac))でのコマンド実行をJavaプログラムから実行するということになります。

こちらのサイトを参考にすると、実行方法としては以下のようにコードを書きます。

Rumtime.getRuntime().exec(コマンド);

しかし、下のようなエラーが出ました。

java.io.IOException: Cannot run program "cls": CreateProcess error=2, 指定されたファイルが見つかりません。
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
at java.lang.Runtime.exec(Runtime.java:621)
at java.lang.Runtime.exec(Runtime.java:451)
at java.lang.Runtime.exec(Runtime.java:348)
at jp.zenryoku.rpg.util.ConsoleUtils.clearConsole(ConsoleUtils.java:172)
at jp.zenryoku.rpg.TextRpgLogic.updateData(TextRpgLogic.java:115)
at jp.zenryoku.rpg.TextRpgGameEngine.start(TextRpgGameEngine.java:40)
at jp.zenryoku.rpg.GameMain.main(GameMain.java:16)
Caused by: java.io.IOException: CreateProcess error=2, 指定されたファイルが見つかりません。
at java.lang.ProcessImpl.create(Native Method)
at java.lang.ProcessImpl.<init(ProcessImpl.java:444)at java.lang.ProcessImpl.start(ProcessImpl.java:139)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
... 7 more

EclipseからMainメソッドを起動した場合でした。

Fix

調べてみると下のようなコードでコンソールをクリアdできるようだ。

new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();

ただし、Eclipseではちゃんとクリアできないが、JARファイルから起動したときはちゃんとクリアされた。

関連ページ一覧

EclipseセットアップWindows版

Eclipse セットアップ

  1. Java Install Eclipse〜開発ツールのインストール〜
  2. TensorFlow C++環境〜EclipseCDTをインストール〜
  3. Setup OpenGL with JavaJOGLを使う準備 for Eclipse
  4. Eclipse Meven 開発手順〜プロジェクトの作成〜
  5. Java OpenCV 環境セットアップ(on Mac)
  6. Eclipse SceneBuilderを追加する
  7. JavaFX SceneBuilder EclipseSceneBuilder連携~

Java Basic一覧

  1. Java Basic Level 1 〜Hello Java〜

JUnitの使い方~テストクラスの作成と実行~


JUnitの設定を行う。

EclipseでJUnitの設定を行います。

  1. プロジェクトを右クリック
  2. ビルドパスを選択する
  3. ライブラリの追加を選択
  4. JUnitを選択

テストするためのクラスを作成する。

今回は、サンプルなので簡単なものです。
ずばり、下のようなクラスを作成しました。

package jp.zenryoku.sample;

/**
 * JUnitの作成から実行までのサンプルクラス
 * @author 作成者の名前
 *
 */
public class JUnitSample {
    /** 定数 */
    private static final String TITLE = "JUnitサンプル";
    /** フィールド変数 */
    private int age;

    public JUnitSample() {
        // 年齢を設定する
        age = 10; // とりあえずは10歳にする
    }

    /**
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * @param age セットする age
     */
    public void setAge(int age) {
        this.age = age;
    }

}
  • 定数として「TITLE」を定義
  • フィールド変数に年齢を定義
  • コンストラクタで年齢を10に設定
  • メソッドとして年齢のGetterSetterを作成

JUnitテストクラスを作成

テストクラスを作成するときは、(自分の常識内では)以下のように作成します。

  1. パッケージ名はテスト対象クラスと同じ
  2. テスト対象クラス+Testという名前にする

テストクラスを作成するときには、テスト対象クラスを定数として保持してしまうと楽なのでそのようにしています。状況によりstatic(静的)でやるべきか、そうしないべきかの判断は、使用したいアノテーションで判断するとよいと思います。

例:
1.テストクラスを起動するときに一度だけ起動するのを「@BeforeClass」アノテーションを使用するならば、static修飾子をつける必要がある。
2.テストケースの実行時に必ずコンストラクタを起動するのであれば、「@Before」を使用するとよい

\@Beforeを使用する場合

上に作成したテストケースを修正して、「@BeforeClass」アノテーションを使用しないパターンで実装してみます。

ここでコンストラクタに引数を追加したものを追加します。具体的には下のようなコードになります。

public JUnitSample(int age) {
    this.age = age;
}

そして、実行するテストに関しては、下のようになります。

package jp.zenryoku.sample;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * JUnitテストクラス: パッケージ名が同じなのでインポートしなくてよい
 * @author 作成者の名前
 */
public class JUnitSampleTest {
    /** テスト対象クラス(テスト実行時には必ず1つなのでstaticでよい) */
    private JUnitSample target;

    /**
     * このテストクラスをインスタンス化するときの処理。
     * このメソッドは1度だけ動く
     */
    @BeforeClass
    public static void initClass() {
        // テスト対象クラスをインスタンス化
//      target = new JUnitSample();
    }

    /**
     * controll + spaceでインポートできる。
     * テストを実行する前の準備処理、テストケースが動くたびに動く
     */
    @Before
    public void initTest() {
//      // 15歳に設定しなおす。
//      target.setAge(15);
        target = new JUnitSample(12);
    }

    /**
     * テストケース1:年齢(age)が15歳に設定されているか確認する。
     */
    @Test
    public void test01() {
        // 警告が出るのでstaticインポートに変更する。
        assertEquals(12, target.getAge());
    }
}

そして、コンストラクタ以外でも年齢の設定を変更できることを確認するテストケースを追加します。

/**
 * テストケース2:年齢を5歳に設定しなおしたときのテスト
 */
@Test
public void test02() {
    target.setAge(5);
    assertEquals(5, target.getAge());
}

関連ページ一覧

Eclipseセットアップ(Windows版)

Eclipse セットアップ(MAC版)

  1. Java Install Eclipse〜開発ツールのインストール〜
  2. TensorFlow C++環境〜EclipseCDTをインストール〜
  3. Setup OpenGL with JavaJOGLを使う準備 for Eclipse
  4. Eclipse Meven 開発手順〜プロジェクトの作成〜
  5. Java OpenCV 環境セットアップ(on Mac)
  6. Eclipse SceneBuilderを追加する
  7. JavaFX SceneBuilder EclipseSceneBuilder連携~

Java Basic一覧

  1. Java Basic Level 1 〜Hello Java〜
  2. Java Basic Level2 〜Arithmetic Calculate〜
  3. Java Basic Level3 〜About String class〜
  4. Java Basic Level 4〜Boolean〜
  5. Java Basic Level 5〜If Statement〜
  6. Java Basic Summary from Level1 to 5
  7. Java Basic Level 6 〜Traning of If statement〜
  8. Java Basic Level8 〜How to use for statement〜
  9. Java Basic Level 8.5 〜Array〜
  10. Java Basic Level 9〜Training of for statement〜
  11. Java Basic Level 10 〜While statement 〜
  12. Java Basic Swing〜オブジェクト指向〜
  13. Java Basic Swing Level 2〜オブジェクト指向2〜
  14. サンプル実装〜コンソールゲーム〜
  15. Java Basic インターフェース・抽象クラスの作り方
  16. Java Basic クラスとは〜Step2_1〜
  17. Java Basic JUnit 〜テストスイートの作り方〜

Git関連

  1. Java Git clone in Eclipse 〜サンプルの取得〜
  2. Eclipse Gitリポジトリの取得 GitからソースをPullしよう〜
  3. IntelliJ IDEA GitGitリポジトリからクローン〜

JavaFX関連ページ

  1. Eclipse SceneBuilderを追加する
  2. JavaFX SceneBuilder 〜EclipseとSceneBuilder連携~
  3. JavaFX SceneBuilder〜ボタンにメソッドを割り当てるワンポイント〜
  4. Java プロコンゲーム 〜見た目の作成(SceneBuilderの使用)〜

ステップアップ関連ページ一覧

  1. Java 初めてでも大丈夫〜ステップアッププログラミングのススメ〜
  2. ステップアッププログラミング〜Java FxでHelloWorld解説〜
  3. Java StepUpPrograming〜JavaFX で四則計算〜
  4. Java StepUpPrograming〜JavaFXで画面切り替えを作る1〜
  5. Java StepUpPrograming〜JavaFXで画面切り替え2ボタン作成〜
  6. Java StepUpPrograming〜JavaFXで画面切り替え3アクション〜
  7. Java StepUpPrograming〜JavaFXで画面切り替え4Pane切り替え〜
  8. Java StepUpPrograming〜JavaFXで画面切り替え5WebEngine

JavaFX + ND4Jで機械学習準備

  1. JavaFX + ND4J〜数学への挑戦1:ND4Jのインストール〜
  2. JavaFX + ND4J〜数学への挑戦2: 行列の計算〜
  3. Java + ND4J 〜数学への挑戦3: ベクトル(配列)の作成方法〜

オブジェクト指向関連ページ

  1. [オブジェクト指向の概念1〜OracleDocのチュートリアル1〜](https://zenryokuservice.com/wp/2019/10/301. /%e3%82%aa%e3%83%96%e3%82%b8%e3%82%a7%e3%82%af%e3%83%88%e6%8c%87%e5%90%91%e3%81%ae%e6%a6%82%e5%bf%b5-%e3%80%9coracledoc%e3%81%ae%e3%83%81%e3%83%a5%e3%83%bc%e3%83%88%e3%83%aa%e3%82%a2%e3%83%ab%ef%bc%91/)
  2. オブジェクト指向の概念2〜クラスとは〜

Java ミニゲーム ソース 〜じゃんけんゲーム in Console 完成〜

コンソール版のじゃんけんゲームを作成しました。
しかし、とりあえず動く状況なので。。。

これに、細かい部分を作ってしまおうと思います。
まずは、バグ退治です。。。がしかしその前に処理の概要をいかに記載します。

  1. プログラムを起動する(Mainクラスのメインメソッド)
  2. コマンドで「exe」を入力してエンターキー押下
  3. じゃんけんゲームの起動(FirstCls#execute())
  4. じゃんけんゲームの入力を待つ
  5. 「1〜3」の入力かチェック
  6. 乱数を生成し CPUの手とする
  7. 両者の勝敗判定を行う

そして、修正した結果(差分)はこちらのリンクで確認できます。

バグのないようですが、じゃんけんゲームの入力時に「1〜3以外の値」が入力された時にMapから値が取得できず。。。
playerの手がnullになります。そして、処理は次へ行ってしまうので、「???」となります。

具体的なコードは下の部分です。
メインメソッドは下の部分で、FirstCls#handleInput()を呼び出しています。
Mainクラス

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String input = scan.next();

        FirstCls first = new FirstCls();
        if ("exe".equals(input)) {
            first.execute(scan);
        }
        boolean isNumber = first.isNumberString(input);
        if (isNumber) {
            System.out.println(input + "は数字です。");
        } else {
            System.out.println(input + "は数字ではありません。");
        }
    }
}

FirstCls#execute()でじゃんけんゲームが開始されます。

FirstClsクラス

public void handleInput(String input) {
    System.out.println("入力値: " + input);
    if (isNumberString(input)) {
        System.out.println(input + "は、数字です");
    } else {
        System.out.println(input + "は、数字ではありません");
    }
}

クラス名がリンクになっていますが、これはGithubへのリンクになります。

修正する(修正内容)

修正方法としては、チェック処理を入れてやります。
そして「クラスの使い方」という観点から、チェッククラスを作成します。

余計な音が履いていますが、これを作成した時の動画です。

ここで追加した実装はCheckUtilクラスです。
このクラスは、実装の過程で、メソッドが増えていきましたが、まぁそんなもんでしょう。

ちなみに、このクラスのメソッドは、全て「静的メソッド」と呼ばれるメソッドです。
呼び出す時にクラス名.メソッド名という形で、呼び出します。

チェック処理

このチェック処理のポイントはズバリ「正規表現」です。
使用している以下の正規表現は0〜9の文字にマッチするのであればTRUEを変えす(そうでなければFALSEを返す)メソッドを使用しています。
そして、同じ名前のメソッドがあります。並べてみると違いが一目瞭然です。

public static boolean isNumber(String numberStr) {};
public static boolean isNumber(String numberStr, String range) {};

そして、Stringクラスにあるメソッドを使用しています。この引数に渡す文字列が「正規表現」であり、このメソッドの返り値が判定結果になります。

numberStr.matches(range)

オーバーロード

上のような実装のことを「メソッドのオーバーロード」と言います。親クラスのメソッドを上書きする「オーバーライド」とこんがらないように気をつけてください。

処理の内容に関してですが
・引数が1つのメソッドは単純に「数字の入力かチェック」
・引数が2つのメソッドは、数字の範囲を指定してチェック」
というように、処理の内容が若干違います。

初めに「0-9の入力(数値入力)チェック」を作成したのですが、じゃんけんで使用するのは1〜3までだけではないか。。。と気がついたので、数字入力チェックに「範囲」を追加しました。

public class CheckUtil {
    /** 0-9(数字)判定をする時の正規表現 */
    public static final String REGREX = "[0-9]";

    /** 1-3までの判定に使用する正規表現 */
    public static final String REG_1_TO_3 = "[1-3]";

    /**
     * 必須入力チェック、第二引数にあう正規表現でのチェックを行う
     * 
     * @param numberStr 検証する文字列
     * @param range 判定用の正規表現
     * @return true: 正規表現にマッチ false: マッチしない
     */
    public static boolean isNumber(String numberStr, String range) {
        // 正規表現で判定します。数字のrangeに当てはまる時にtrue
        if (isEmpty(numberStr) && numberStr.length() != 1) {
            return false;
        }
        if (numberStr.matches(range)) {
            return true;
        }
        return false;   }
    /**
     * 引数の1文字が数字かどうかの判定をする。。
     * 
     * @param numberStr
     * @return true: 引数が0-9 false: 0-9ではない
     */
    public static boolean isNumber(String numberStr) {
        // 正規表現で判定します。数字の0-9に当てはまる時にtrue
        if (isEmpty(numberStr) && numberStr.length() != 1) {
            return false;
        }
        if (numberStr.matches("[0-9]")) {
            return true;
        }
        return false;
    }

    /**
     * 引数に渡した文字列が、Null、またはから文字("")
     * @param str 判定する文字列
     * @return ture; 
     */
    public static boolean isEmpty(String str) {
        if (str == null || "".equals(str)) {
            return true;
        }
        return false;
    }
}

ちなみに、静的メソッドは、static修飾子をつけて実装します。インスタンスを生成しないので、メモリの節約になりますが、作りすぎると余計な負担(メモリ使用)になるので注意です。

まとめ

今までに作成したクラスFirstClsでの処理を修正しました。
くどいようですが、Mainメソッドは修正していません。

そして、追加したCheckUtilクラスはチェック担当のクラスです。

なので、このクラスにはチェック処理しか追加しません。



関連ページ一覧

Eclipse セットアップ

  1. Java Install Eclipse〜開発ツールのインストール〜
  2. TensorFlow C++環境〜EclipseCDTをインストール〜
  3. Setup OpenGL with JavaJOGLを使う準備 for Eclipse
  4. Eclipse Meven 開発手順〜プロジェクトの作成〜
  5. Java OpenCV 環境セットアップ(on Mac)
  6. Eclipse SceneBuilderを追加する
  7. JavaFX SceneBuilder EclipseSceneBuilder連携~

Java Basic一覧

  1. Java Basic Level 1 〜Hello Java〜
  2. Java Basic Level2 〜Arithmetic Calculate〜
  3. Java Basic Level3 〜About String class〜
  4. Java Basic Level 4〜Boolean〜
  5. Java Basic Level 5〜If Statement〜
  6. Java Basic Summary from Level1 to 5
  7. Java Basic Level 6 〜Traning of If statement〜
  8. Java Basic Level8 〜How to use for statement〜
  9. Java Basic Level 8.5 〜Array〜
  10. Java Basic Level 9〜Training of for statement〜
  11. Java Basic Level 10 〜While statement 〜
  12. Java Basic Swing〜オブジェクト指向〜
  13. Java Basic Swing Level 2〜オブジェクト指向2〜
  14. サンプル実装〜コンソールゲーム〜
  15. Java Basic インターフェース・抽象クラスの作り方
  16. Java Basic クラスとは〜Step2_1〜
  17. Java Basic JUnit 〜テストスイートの作り方〜

Git関連

  1. Java Git clone in Eclipse 〜サンプルの取得〜
  2. Eclipse Gitリポジトリの取得 GitからソースをPullしよう〜
  3. IntelliJ IDEA GitGitリポジトリからクローン〜

JavaFX関連ページ

  1. Eclipse SceneBuilderを追加する
  2. JavaFX SceneBuilder 〜EclipseとSceneBuilder連携~
  3. JavaFX SceneBuilder〜ボタンにメソッドを割り当てるワンポイント〜
  4. Java プロコンゲーム 〜見た目の作成(SceneBuilderの使用)〜

ステップアップ関連ページ一覧

  1. Java 初めてでも大丈夫〜ステップアッププログラミングのススメ〜
  2. ステップアッププログラミング〜Java FxでHelloWorld解説〜
  3. Java StepUpPrograming〜JavaFX で四則計算〜
  4. Java StepUpPrograming〜JavaFXで画面切り替えを作る1〜
  5. Java StepUpPrograming〜JavaFXで画面切り替え2ボタン作成〜
  6. Java StepUpPrograming〜JavaFXで画面切り替え3アクション〜
  7. Java StepUpPrograming〜JavaFXで画面切り替え4Pane切り替え〜
  8. Java StepUpPrograming〜JavaFXで画面切り替え5WebEngine

JavaFX + ND4Jで機械学習準備

  1. JavaFX + ND4J〜数学への挑戦1:ND4Jのインストール〜
  2. JavaFX + ND4J〜数学への挑戦2: 行列の計算〜
  3. Java + ND4J 〜数学への挑戦3: ベクトル(配列)の作成方法〜

JavaFX ワンポイント 〜Fontを指定する〜

TextFIeldやTextAreaを使用するときにFontの設定をしてやると大きさなど変更できます。

設定方法は以下のようなコードです。

newWindow = new Stage();
StackPane stack = new StackPane();
textArea = new TextArea();
textArea.setFont(Font.font("MS UI Gothic", FontWeight.BLACK, 19));
textArea.setOnKeyPressed(keyEvent -> {
    KeyCode code = keyEvent.getCode();
    if (keyEvent.isShiftDown() && KeyCode.SPACE.equals(code)) {
        newWindow.close();
        isTextIn = false;
    }
});
textArea.setOnKeyReleased(keyEvent -> {
    KeyCode code = keyEvent.getCode();
    if (keyEvent.isShiftDown() && KeyCode.ENTER.equals(code)) {
        textArea.setText("");
        textArea.positionCaret(0);
    }
});
stack.getChildren().add(textArea);
Scene scene = new Scene(stack, 450, 100);
newWindow.setScene(scene);
newWindow.initModality(Modality.WINDOW_MODAL);
newWindow.initOwner(primary);
newWindow.setX(primary.getWidth() * 0.4);
newWindow.setY(primary.getHeight() * 0.8);
newWindow.show();

return newWindow;

TextAreaで実装しましたが、これはTextFieldにも使用できます。

でわでわ。。。



関連ページ一覧

Eclipse セットアップ

  1. Java Install Eclipse〜開発ツールのインストール〜
  2. TensorFlow C++環境〜EclipseCDTをインストール〜
  3. Setup OpenGL with JavaJOGLを使う準備 for Eclipse
  4. Eclipse Meven 開発手順〜プロジェクトの作成〜
  5. Java OpenCV 環境セットアップ(on Mac)
  6. Eclipse SceneBuilderを追加する
  7. JavaFX SceneBuilder EclipseSceneBuilder連携~

Java Basic一覧

  1. Java Basic Level 1 〜Hello Java〜
  2. Java Basic Level2 〜Arithmetic Calculate〜
  3. Java Basic Level3 〜About String class〜
  4. Java Basic Level 4〜Boolean〜
  5. Java Basic Level 5〜If Statement〜
  6. Java Basic Summary from Level1 to 5
  7. Java Basic Level 6 〜Traning of If statement〜
  8. Java Basic Level8 〜How to use for statement〜
  9. Java Basic Level 8.5 〜Array〜
  10. Java Basic Level 9〜Training of for statement〜
  11. Java Basic Level 10 〜While statement 〜
  12. Java Basic Swing〜オブジェクト指向〜
  13. Java Basic Swing Level 2〜オブジェクト指向2〜
  14. サンプル実装〜コンソールゲーム〜
  15. Java Basic インターフェース・抽象クラスの作り方
  16. Java Basic クラスとは〜Step2_1〜
  17. Java Basic JUnit 〜テストスイートの作り方〜

Git関連

  1. Java Git clone in Eclipse 〜サンプルの取得〜
  2. Eclipse Gitリポジトリの取得 GitからソースをPullしよう〜
  3. IntelliJ IDEA GitGitリポジトリからクローン〜

JavaFX ワンポイント 〜新しいWindowを立ち上げる〜

JavaFXを起動するときにすでにウィンドウを1つ起動していますが、さらにウィンドウを使いたいとき。。。

今回はそんなところを「ワンポイントレッスン」的に記載したいと思います。

ちなみに、JavaFXはこんな感じのものです。余計な音が入っています。そして、文言を表示する部分でnewWindowを使用しています。

ウィンドウを新しく作る

WindowはStageです。なので、下のように実装したらできました。
参考にしたサイトはこちらです。

private Stage createNewWindow(Stage primary) {
    newWindow = new Stage();
    StackPane stack = new StackPane();
    textArea = new TextArea();
    textArea.setOnKeyPressed(keyEvent -> {
        KeyCode code = keyEvent.getCode();
        if (keyEvent.isShiftDown() && KeyCode.SPACE.equals(code)) {
            newWindow.close();
            isTextIn = false;
        }
    });
    textArea.setOnKeyReleased(keyEvent -> {
        KeyCode code = keyEvent.getCode();
        if (keyEvent.isShiftDown() && KeyCode.ENTER.equals(code)) {
            textArea.setText("");
            textArea.positionCaret(0);
        }
    });
    stack.getChildren().add(textArea);
    Scene scene = new Scene(stack, 250, 50);
    newWindow.setScene(scene);
    newWindow.initModality(Modality.WINDOW_MODAL);
    newWindow.initOwner(primary);
    newWindow.setX(primary.getWidth() * 0.4);
    newWindow.setY(primary.getHeight() * 0.8);
    newWindow.show();

    return newWindow;
}

作成したウィンドウにキーイベントを追加して見ました。

ちなみに、
簡単ですが、こんな感じで。。。

でわでわ。。。



関連ページ一覧

Eclipse セットアップ

  1. Java Install Eclipse〜開発ツールのインストール〜
  2. TensorFlow C++環境〜EclipseCDTをインストール〜
  3. Setup OpenGL with JavaJOGLを使う準備 for Eclipse
  4. Eclipse Meven 開発手順〜プロジェクトの作成〜
  5. Java OpenCV 環境セットアップ(on Mac)
  6. Eclipse SceneBuilderを追加する
  7. JavaFX SceneBuilder EclipseSceneBuilder連携~

Java Basic一覧

  1. Java Basic Level 1 〜Hello Java〜
  2. Java Basic Level2 〜Arithmetic Calculate〜
  3. Java Basic Level3 〜About String class〜
  4. Java Basic Level 4〜Boolean〜
  5. Java Basic Level 5〜If Statement〜
  6. Java Basic Summary from Level1 to 5
  7. Java Basic Level 6 〜Traning of If statement〜
  8. Java Basic Level8 〜How to use for statement〜
  9. Java Basic Level 8.5 〜Array〜
  10. Java Basic Level 9〜Training of for statement〜
  11. Java Basic Level 10 〜While statement 〜
  12. Java Basic Swing〜オブジェクト指向〜
  13. Java Basic Swing Level 2〜オブジェクト指向2〜
  14. サンプル実装〜コンソールゲーム〜
  15. Java Basic インターフェース・抽象クラスの作り方
  16. Java Basic クラスとは〜Step2_1〜
  17. Java Basic JUnit 〜テストスイートの作り方〜

Git関連

  1. Java Git clone in Eclipse 〜サンプルの取得〜
  2. Eclipse Gitリポジトリの取得 GitからソースをPullしよう〜
  3. IntelliJ IDEA GitGitリポジトリからクローン〜

Java Basic Class 〜メインメソッドを変更しないで処理を変える〜

クラスを使用すると

メインメソッドを変更しなくても処理を変更できます。

具体的に、下のようにやります。
以前作成したメインメソッド

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String input = scan.next();

        FirstCls first = new FirstCls();
        boolean isNumber = first.isNumberString(input);
        if (isNumber) {
            System.out.println(input + "は数字です。");
        } else {
            System.out.println(input + "は数字ではありません。");
        }
    }
}

このクラスから呼び出しているFirstClsを修正してやれば、Mainクラスは修正する必要がありません。

なんか「とんち」のような話ですが(笑)

応用レベル1

現段階では、応用幅が小さいのでMainメソッドを修正します。

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String input = scan.next();

        FirstCls first = new FirstCls();
        if ("exe".equals(input)) {
            first.execute();
        }
        boolean isNumber = first.isNumberString(input);
        if (isNumber) {
            System.out.println(input + "は数字です。");
        } else {
            System.out.println(input + "は数字ではありません。");
        }
    }
}

FirstClsのexecuteメソッドを起動するように修正しました。

クラスに処理を追加する

はじめの入力で「exe」と入力するとFirdtClsのexecuteメソッドが起動します。

単純に、FirstClsの中に、適当な処理を実装しただけです。

public void execute(Scanner scan) {
    System.out.println("*** EXECUTEを起動します ***");
    Map<String, String> map = new HashMaplt;>();
    map.put("test", "Testing this program!");
    map.put("prac", "Practice this program!");
    map.put("try", "Try this program!");
    while(true) {
        System.out.print("コマンドを入力してください: ");
        String str = scan.next();
        if (map.containsKey(str) == false) {
            break;
        }
        System.out.println(map.get(str));
    }
}

今回は、Mapインターフェースを使用して見ました。
キーと値がセットになって、データの取り出し、保存を行うことができます。
ここで言う保存はJavaが起動している間だけの保存です。

このままでは、大した発展があったようには思えませんので、一捻り加えます。ちなみに、execute()の処理が終わった後に、何かしらの文言が出ます。

一捻り

単純ですが、FirstClsにあるメソッドisNumberString()を呼び出すように修正します。

public void execute(Scanner scan) {
    System.out.println("*** EXECUTEを起動します ***");
    Map<String, String> map = new HashMap<>();
    map.put("test", "Testing this program!");
    map.put("prac", "Practice this program!");
    map.put("try", "Try this program!");
    while(true) {
        System.out.print("コマンドを入力してください: ");
        String str = scan.next();
        if (map.containsKey(str) == false) {
            break;
        }
        isNumberString(str);
        System.out.println(map.get(str));
    }
}

こんな感じです。
今日のところは、ここまでにしておきます。

でわでわ。。。



Java Basic Class 〜クラスを使うサンプル〜

前回は、クラスを作成してそれを撃とかして見ました。

しかし、コードと説明だけで実行していませんでした。今回は、それを実行してみようと思います。

前回やったこと

メインメソッドがプログラムの起動する主軸になります。

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String input = scan.next();

        FirstCls first = new FirstCls();
        first.handleInput(input);
    }
}

この処理は、標準入力を受け付け、受け取った文字列をFirstClsのメソッドhandleInput()に渡しています。

String[] args -> プログラム引数
System.in -> 標準入力
System.out -> 標準出力

これを下のような書き方で表現できます。
「FirstCls#handleInput()に受け取った文字列を渡す」

実際に作成したFirstClsの内容は以下のようになっています。

public class FirstCls {

    public void handleInput(String input) {
        System.out.println("入力値: " + input);
        if (isNumberString(input)) {
            System.out.println(input + "は、数字です");
        } else {
            System.out.println(input + "は、数字ではありません");
        }
    }

    public boolean isNumberString(String str) {
        // [0-9]は正規表現と言います。
        boolean isNumber = str.matches("[0-9]");
        return isNumber;
    }

    /** 使用しないので下のアノテーションをつける */
    @Deprecated
    public void printSomething(String[] args) {
        //  プログラム引数に値があるときは表示する
        if (args.length != 0) {
            for (int i = 0; i < args.length; i++) {
                System.out.println("プログラム引数[" + i + "]: " + args[i]);
            }
        }
        System.out.println("1 + 1 = " + (1 + 1));
    }
}

呼び出しているメソッドはhandleInputなので、他のメソッドは関係ありません。(影響がありません)

なので、今回は、別のメソッドを呼び出すように変えて見ました。

処理概要

Mainクラス=メインメソッドのあるクラス
FirstCls=入力値を操作するクラス

  1. 標準入力を受ける
  2. 入力値に対して何かしらの処理をする
    ※今回は、入力値が数字かどうか判定する処理

【FirstClsクラスについて】
このクラスには、複数のメソッドを実装しているが、必要なものは使用する。必要ないものは使用しない。
つまり、処理を実装するためのクラスです。

【クラス構成について】
・Mainクラスは、Mainメソッドを起動するためのクラス
・FirstClsクラスは、処理を実装するためのクラス

この実装に対して、処理の結果を変更したいのであれば、FirstCls#handleInput()を修正すれば良いのです。

処理詳細

【メインメソッド】

// 標準入力を受け取る準備
Scanner scan = new Scanner(System.in);
// 標準入力受付と受け取り
String input = scan.next();
// FirstClsのインスタンスを生成
FirstCls first = new FirstCls();
// FirstCls#handleInput()を呼び出す
first.handleInput(input);

// 処理終了

【FirstCls】
実装したメソッドのうち「isNumberString」と「handleInput」を使用しています。

ポイント

クラスといっても結局はメソッド呼び出しを行なっているのと変わりません。
なので、下のようにメソッドを呼び出すのも、クラスのインスタンスを取得してメソッドを呼び出すのも大した違いはありません。
【パターンA】: FirstCls#isNumberString()を使用する

public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    String input = scan.next();

    FirstCls first = new FirstCls();
    boolean isNumber = first.isNumberString(input);
    if (isNumber) {
        System.out.println(input + "は数字です。");
    } else {
        System.out.println(input + "は数字ではありません。");
    }
}

【パターンB】: FirstCls#isNumberString()に実装してある処理をここでも実装する

public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    String input = scan.next();

    FirstCls first = new FirstCls();
    boolean isNumber = input.matches("[0-9]{1,}");
    if (isNumber) {
        System.out.println(input + "は数字です。");
    } else {
        System.out.println(input + "は数字ではありません。");
    }
}

このように、「クラス」と言うオブジェクトの中に様々な処理を実装して、インスタンスを取得すれば、その処理を呼び出すことができます。

インスタンスを取得しなくても、呼び出す方法がありますが、それはまた別の機会にしましょう。
ちなみに、それは「静的呼び出し」といいstatic修飾子を使用します。

ちなみに、このコードにはバグがあります。それはどこでしょうか?
=> 入力した文字列が複数の場合、想定と違う結果が返ってくる
とりあえずは、こんなところで。。。

でわでわ。。。



Java Basic Class 〜クラスを作ってクラスを理解する〜

久しぶりに、Javaの基本をやろうと思います。
Javaの基本といってもいろいろあるので、クラスの作り方をメインにやろうと思います。

早速作りましょう

とりあえずは、動かすのにメインメソッドが必要ですので、このメインメソッドを作成します。

作り方は、今までにやってきたので割愛します。

ここでのポイントは、MainメソッドのあるMainクラスを作成すると言うところです。

my.sample.Main

public class Main {
    public static void main(String[] args) {
        // 中身はまだない。。。
    }
}

このクラスから処理が始まります。

何をするか考える

設計の工程になります。。。

Step1

しかし、初めての人にもわかるよう、ハローワールドを実装します。

public class Main {
    public static void main(String[] args) {
        //  ハローワールド
        System.out.println("Hello World!");
    }
}
Step⒉

しかしこれでは、物足りない。。。
プログラム引数に、値を渡して、プログラム引数に値がある場合に表示すると言うものにしましょう

public class Main {
    public static void main(String[] args) {
        //  プログラム引数に値があるときは表示する
        if (args.length != 0) {
            System.out.println("プログラム引数:" + args[0]);
        }
        System.out.println("Hello World!");
    }
}
Step3

いやいや。。。プログラム引数が1つだけとは限らないので、そいつをどうにかしよう。

つまり、プログラム引数の数だけ表示しよう!

public class Main {
    public static void main(String[] args) {
        //  プログラム引数に値があるときは表示する
        if (args.length != 0) {
            for (int i = 0; i < args.length; i++) {
                System.out.println("プログラム引数[" + i + "]: " + args[0]);
            }
        }
        System.out.println("Hello World!");
    }
}
Step4

次は、文字表示だけじゃ面白くないから計算をしよう。

public class Main {
    public static void main(String[] args) {
        //  プログラム引数に値があるときは表示する
        if (args.length != 0) {
            for (int i = 0; i < args.length; i++) {
                System.out.println("プログラム引数[" + i + "]: " + args[0]);
            }
        }
        System.out.println("1 + 1 = " + (1 + 1));
    }
}

Step5

ここまできたら、クラスも作ってみよう。
しかし、今まで作成したコードは、書き換えてきたから、また呼び出したい時には、どうしたら良いだろうか?

クラスを使う

クラスを使うと、呼び出すメソッドを変えてやるだけで今までの作成したコードを実行できます。

Step1〜4までに作成したコードはどこかにいってしまいましたが、今後作成するプログラムは残せるように、クラスを作りながら進みます。

Step6: クラスを作る

とりあえず、今メインメソッドにある処理は邪魔なので、作成したクラスへ移動してしまいます。
新たに作成したクラスはFirstClsです、パッケージが違うのでインポートする必要があります。

そして、Mainクラスはこのようになりました。

public class Main {
    public static void main(String[] args) {
        FirstCls first = new FirstCls();
        first.printSomething(args);
    }
}

FirstCls

public class FirstCls {
    public void printSomething(String[] args) {
        //  プログラム引数に値があるときは表示する
        if (args.length != 0) {
            for (int i = 0; i < args.length; i++) {
                System.out.println("プログラム引数[" + i + "]: " + args[0]);
            }
        }
        System.out.println("1 + 1 = " + (1 + 1));
    }
}

処理の結果は変わりません。

そして、Eclipseでのパッケージ構成は下のようになっています。

ここからです。

Step7: クラスを使うメリット

現状、作成したプログラムは、
なんとなく作成した、意味のない処理が動いている状態です。

これは、とりあえずFirstClsによけておき、入力を受け取るプログラムを追加したいともいます。
これは、全ての処理の始まりになりますので、Mainクラスに実装します。実際に動かした時の動画です。

Step8: 標準入力を受ける

今までに処理結果をコンソールに表示していました。
ここは、「標準出力」と言う場所で、System.outで表現される(メモリ)領域です。

とりあえずここに表示するSystem.out.printメソッドで今まで表示を行なっていました。

次は、逆に入力、出力に対して入力を受け付けるプログラムを書きます。
Mianクラスに実装します。

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String input = scan.next();

        FirstCls first = new FirstCls();
        first.printSomething(args);
    }
}

そして、取得した標準入力をコントロールするためのメソッドをFirstClsに作成します。

public class FirstCls {

    public void handleInput(String input) {
        System.out.println("入力値: " + input);
    }

    /** 使用しないので下のアノテーションをつける */
    @Deprecated
    public void printSomething(String[] args) {
        //  プログラム引数に値があるときは表示する
        if (args.length != 0) {
            for (int i = 0; i < args.length; i++) {
                System.out.println("プログラム引数[" + i + "]: " + args[i]);
            }
        }
        System.out.println("1 + 1 = " + (1 + 1));
    }
}
Step9: まずはハローワールド

入力値をコンソールに表示するプログラムを作成しました。

上のような出力ができます。

作成したhandleInput()をそのままにしておき、次は引数が数字かどうか判定するメソッドを作成します。

public boolean isNumberString(String str) {
    // [0-9]は正規表現と言います。
    boolean isNumber = str.matches("[0-9]");
    return isNumber;
}

そして、これを初めに作ったメソッドから呼び出すようにします。

public void handleInput(String input) {
    System.out.println("入力値: " + input);
    if (isNumberString(input)) {
        System.out.println(input + "は、数字です");
    } else {
        System.out.println(input + "は、数字ではありません");
    }
}

こんな感じの実行結果が見れます。

作成したコードはこちらから参照(ダウンロード)できます
Mainクラス
FirstClsクラス

まとめ

このように、主軸になる処理を中心にして、処理を繋げられるように、処理を分断(機能レベル、処理レベル色々ありますが。。。)。

そして、組み合わせて実行!と言うように、なるべく修正、追加する作業を減らせるように作るとクールなプログラムと言えるでしょう。

あー自分も美しいプログラムが書けるようになりたい!

でわでわ。。。

関連ページ

Eclipse セットアップ

  1. Java Install Eclipse〜開発ツールのインストール〜
  2. TensorFlow C++環境〜EclipseCDTをインストール〜
  3. Setup OpenGL with JavaJOGLを使う準備 for Eclipse
  4. Eclipse Meven 開発手順〜プロジェクトの作成〜
  5. Java OpenCV 環境セットアップ(on Mac)
  6. Eclipse SceneBuilderを追加する
  7. JavaFX SceneBuilder EclipseSceneBuilder連携~

Java Basic一覧

  1. Java Basic Level 1 〜Hello Java〜
  2. Java Basic Level2 〜Arithmetic Calculate〜
  3. Java Basic Level3 〜About String class〜
  4. Java Basic Level 4〜Boolean〜
  5. Java Basic Level 5〜If Statement〜
  6. Java Basic Summary from Level1 to 5
  7. Java Basic Level 6 〜Traning of If statement〜
  8. Java Basic Level8 〜How to use for statement〜
  9. Java Basic Level 8.5 〜Array〜
  10. Java Basic Level 9〜Training of for statement〜
  11. Java Basic Level 10 〜While statement 〜
  12. Java Basic Swing〜オブジェクト指向〜
  13. Java Basic Swing Level 2〜オブジェクト指向2〜
  14. サンプル実装〜コンソールゲーム〜
  15. Java Basic インターフェース・抽象クラスの作り方
  16. Java Basic クラスとは〜Step2_1〜
  17. Java Basic JUnit 〜テストスイートの作り方〜

Git関連

  1. Java Git clone in Eclipse 〜サンプルの取得〜
  2. Eclipse Gitリポジトリの取得 GitからソースをPullしよう〜
  3. IntelliJ IDEA GitGitリポジトリからクローン〜


Java OpenCV エラーの対処 〜CvException /matrix.cpp:465: 〜

Exception in thread "main" CvException [org.opencv.core.CvException: cv::Exception: OpenCV(3.4.3) /opencv/modules/core/src/matrix.cpp:465: error: (-215:Assertion failed) 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows in function 'Mat'
]
at org.opencv.core.Mat.n_submat(Native Method)
at org.opencv.core.Mat.submat(Mat.java:854)
at zenryokuservice.opencv.fx.ImageSlicerMain.loadImg(ImageSlicerMain.java:78)
at zenryokuservice.opencv.fx.ImageSlicerMain.main(ImageSlicerMain.java:107)

このエラーメッセージに、遭遇したら単純に、読み込んだファイルのサイズと読み込もうとしているサイズの指定がうまくいっていません。

URL p = this.getClass().getResource("/" );
System.out.println("*** " + p.getPath());
Mat downloadFile = Imgcodecs.imread(p.getPath());

自分の場合は上のようなコードで、リソース(ファイル)が取得できていませんでした。それゆえにエラー。

Class#getResource()とnew File(パス)で実装する時にルートになる場所が変わるので注意が必要です。

作成したImageSlicerでイメージファイルを切り刻みます。
ソースコードは、こちらに有ります

ポイントは、ループする最中に、xPosとyPosで切り出すファイルの位置をづらしていくところです。
そして、確認用のSwingは最後に出力するイメージが表示されます。。。

private ImageIcon dstImage(String fileName, Mat downloadFile, String sufix, int xPos, int yPos, int size, int times) {
    Rect roi = new Rect(xPos, yPos, size, size);
    System.out.println("x: " + roi.x);
    System.out.println("y: " + roi.y);
    Mat target = downloadFile.submat(roi);
    MatOfByte bytes = new MatOfByte();
    Imgcodecs.imencode(".png", target, bytes);
    byte[] b = bytes.toArray();
    InputStream in = new ByteArrayInputStream(b);
    BufferedImage buf = null;
    try {
        buf = ImageIO.read(in);
        File out = new File("resources/dst/" + fileName + "_" + sufix + ".png");
        ImageIO.write(buf, "png", out);
    } catch(IOException e) {
        e.printStackTrace();
    }
    return new ImageIcon(buf);
}


Java デザインパターン 〜シングルトン パターン〜

Androidアプリ作成の予備知識として、オブジェクト指向、クラスの組み合わせ方の王道としてデザインパターンに関して記載していきます。

作成したコードは、Gitにアップしてあります。

シングルトン

シングルトンパターンは、一個のオブジェクトを共有したい時に使用します。
つまり、プログラムが起動している最中では1つだけ存在するオブジェクト(クラス)になります。

例えば、共通で使用するデータを保持する役目をこのクラスに持たせようとした時に便利は実装方法です。
文言だけではイマイチ。。。なのでコードを交えて記載します。

シングルトンサンプル

実行結果は下のようになります。

Mainクラス
Singletonクラス

処理概要

シングルトンクラス(SingletonCls)を定義しておきます。

public class SingletonCls {
    /** このクラスのインスタンス */
    private static SingletonCls instance;
    /** 設定情報1 */
    private int setting1;
    /** 設定情報2 */
    private String setting2;

    public static SingletonCls getInstance() {
        if (instance == null) {
            instance = new SingletonCls();
        }
        return instance;
    }

    /** コンストラクタは外部から参照不可 */
    private SingletonCls() {
    }

    /**
     * @return the setting1
     */
    public int getSetting1() {
        return setting1;
    }

    /**
     * @param setting1 the setting1 to set
     */
    public void setSetting1(int setting1) {
        this.setting1 = setting1;
    }

    /**
     * @return the setting2
     */
    public String getSetting2() {
        return setting2;
    }

    /**
     * @param setting2 the setting2 to set
     */
    public void setSetting2(String setting2) {
        this.setting2 = setting2;
    }
}

このクラスをMainメソッドから呼び出して使用します。

public class SingletonMain {
    public static void main(String[] args) {
        SingletonMain main = new SingletonMain();
        // シングルトンクラスを取得する(メソッドのstatic呼び出し)
        SingletonCls single = SingletonCls.getInstance();
        single.setSetting1(12);
        single.setSetting2("設定情報2");

        // 設定情報を表示する
        main.showSetting();

        // 設定情報を変更する
        single.setSetting1(99);
        single.setSetting2("こんばんは");

        // 設定情報を表示する
        main.showSetting();
    }

    /** 設定情報を表示する */
    public void showSetting() {
        SingletonCls single = SingletonCls.getInstance();
        System.out.println("**** 設定情報 *****");
        System.out.println("設定情報1: " + single.getSetting1());
        System.out.println("設定情報2: " + single.getSetting2());
        System.out.println("*****************");
    }
}

シングルトンクラスは、getInstance()でしかインスタンスが取得できないように作っています。

public static SingletonCls getInstance() {
    if (instance == null) {
        instance = new SingletonCls();
    }
    return instance;
}

/** コンストラクタは外部から参照不可 */
private SingletonCls() {
}

まとめ

上のように、シングルトンクラスはインスタンスが1つなので、常に保持している値が(各フィールドごとに)1つになります。なので、処理をしている最中に「設定情報」などを変更して何かしらの処理を行う時には便利は実装方法です。
他にも、アイディア次第でいろんなことができます。

余談

これがシングルトンでない場合は。。。
インスタンスが別々になるので、上のコードshowSetting()に引数を与えるとか他の方法をとる必要があります。

/** 設定情報を表示する */
public void showSetting() {
    // この部分を変更する必要がある
    SingletonCls single = SingletonCls.getInstance();
    System.out.println("**** 設定情報 *****");
    System.out.println("設定情報1: " + single.getSetting1());
    System.out.println("設定情報2: " + single.getSetting2());
    System.out.println("*****************");
}

シングルトンの場合は、getInstance()で(static呼び出しなので)いつでも設定情報を持っているインスタンスを取得できますが、これをシングルトンではない実装にするときは下のようになります。

実装は下のようになりました。

//// シングルトンではないパターン ////
NoSingletonCls noSingle = main.new NoSingletonCls();
// インナークラスなので参照可能、普通はこんな実装をしない
noSingle.setting1 = 1;
noSingle.setSetting2("内部設定");
main.showInnerSetting(noSingle);
// 値を変更する
noSingle.setSetting1(33);
noSingle.setSetting2("内部情報123");
main.showInnerSetting(noSingle);

とりあえずは、インスタンスを毎回作成する必要があるので、この部分が無駄になるわけです。
シングルトンは1つなので余計なPCリソース(メモリなど)を使用しなくて良いので、経済的な実装方法です(笑)

でわでわ。。。



関連ページ一覧

Eclipse セットアップ

Java Install Eclipse~開発ツールのインストール~

TensorFlow C++環境~EclipseにCDTをインストール~

Setup OpenGL with Java~JOGLを使う準備 for Eclipse~

Eclipse Meven 開発手順~プロジェクトの作成~

Java OpenCV 環境セットアップ(on Mac)

Eclipse SceneBuilderを追加する

JavaFX SceneBuilder ~EclipseとSceneBuilder連携~

Java Basic一覧

Java Basic Level 1 ~Hello Java~

Java Basic Level2 ~Arithmetic Calculate~

Java Basic Level3 ~About String class~

Java Basic Level 4~Boolean~

Java Basic Level 5~If Statement~

Java Basic Summary from Level1 to 5

Java Basic Level 6 ~Traning of If statement~

Java Basic Level8 ~How to use for statement~

Java Basic Level 8.5 ~Array~

Java Basic Level 9~Training of for statement~

Java Basic Level 10 ~While statement ~

Java Basic Swing~オブジェクト指向~

Java Basic Swing Level 2~オブジェクト指向2~

サンプル実装~コンソールゲーム~

Java Basic インターフェース・抽象クラスの作り方

Java Basic クラスとは~Step2_1~

Java Basic JUnit ~テストスイートの作り方~

Git関連

Java Git clone in Eclipse ~サンプルの取得~

Eclipse Gitリポジトリの取得 ~GitからソースをPullしよう~

IntelliJ IDEA Git~Gitリポジトリからクローン~

JavaFX関連ページ

Eclipse SceneBuilderを追加する

JavaFX SceneBuilder ~EclipseとSceneBuilder連携~

JavaFX SceneBuilder~ボタンにメソッドを割り当てるワンポイント~

Java プロコンゲーム ~見た目の作成(SceneBuilderの使用)~

ステップアップ関連ページ一覧

Java 初めてでも大丈夫~ステップアッププログラミングのススメ~

ステップアッププログラミング~Java FxでHelloWorld解説~

Java StepUpPrograming~JavaFX で四則計算~

Java StepUpPrograming~JavaFXで画面切り替えを作る1~

Java StepUpPrograming~JavaFXで画面切り替え2ボタン作成~

Java StepUpPrograming~JavaFXで画面切り替え3アクション~

Java StepUpPrograming~JavaFXで画面切り替え4Pane切り替え~

Java StepUpPrograming~JavaFXで画面切り替え5WebEngine

JavaFX + ND4Jで機械学習準備

JavaFX + ND4J~数学への挑戦1:ND4Jのインストール~

JavaFX + ND4J~数学への挑戦2: 行列の計算~

Java + ND4J ~数学への挑戦3: ベクトル(配列)の作成方法~

オブジェクト指向関連ページ

[オブジェクト指向の概念1~OracleDocのチュートリアル1~](https://zenryokuservice.com/wp/2019/10/301. /%e3%82%aa%e3%83%96%e3%82%b8%e3%82%a7%e3%82%af%e3%83%88%e6%8c%87%e5%90%91%e3%81%ae%e6%a6%82%e5%bf%b5-%e3%80%9coracledoc%e3%81%ae%e3%83%81%e3%83%a5%e3%83%bc%e3%83%88%e3%83%aa%e3%82%a2%e3%83%ab%ef%bc%91/)

オブジェクト指向の概念2~クラスとは~