今からはじめるプログラミング38


ここまで読んでくれる人はどれくらいいたのか。

よくわからないけれど。

プログラムにだいぶなれたとは思うので、オブジェクト思考的なプログラミング?かどうかはわからないですが、昔参加したプロジェクトで、凄まじい量のコーディング(ほとんどシステムを一人で作った?)をする人がいたので、その方から教わった

オブジェクト指向では、粒度をコントロールしてプログラムする」

ということを実践(できているかはわかりません。)してみる。

 

処理の概要以下のような感じ。

前回で、とりあえずギターのアイコンの画像を作ったけれど、売れている?NFTと比べて、比較して、何が足りない?というかストーリーがなくて、個性がないかな。ただのアイコン。

f:id:yo2an:20210930190848p:plain

もと

この反省点を画像に追加するプログラムをつくろうと思う。

要は、目鼻口をつけて、キャラクターにするのですね。

というわけで、今回は、かなり長々とした文章になりますので、読まない方がいいかも。

 

ここからが本編?

 

「おおまかなわくから実装まで」

(そんなかんじでプログラムする。)

 

とりあえず作りたいのは、
もとある画像に、擬人化?個性をもたせたいので、
「目」を追加してみようと思う。
まぁ「目」も画像ではあるのだけれど。

さて本来はインターフェースから作っていくべきかも、なのですが、
(インターフェースからあぶすとらくと、そして普通のクラスとしての実装)
組み替えていった方が、何が変化したのかわかりやすいと思って、
ひとつのクラスをちょっとずつ組み替えていきます。

というわけで、最初に考えた大枠(粒度のおおきいクラス)です。

例)1。
----------------------------------------
package sample21;

public class CreateI {
    
    private void loadImage() {
        
    }
    
    private void modImage() {
        
    }
    private void outImage() {
        
    }

    public boolean execute() {
        this.loadImage();
        this.modImage();
        this.outImage();
        
        return false;
    }
}
----------------------------------------
まこと名前のセンスがないのが残念ですが、
とりあえず動きはご理解いただけますでしょうか?
わかりませんか。まぁ大枠で何をしたいかを描いてあれば、大丈夫という感じです。


というわけで僕も心配性なので?
mainメソッドを追加して確認しながら作っていきます。

例)2。
---------------------------------------
package sample21;

public class CreateI {
    
    private void loadImage() {
        System.out.println("loadImage()を実行");
    }
    
    private void modImage() {
        System.out.println("modImage()を実行");
    }
    private void outImage() {
        System.out.println("outImage()を実行");
    }

    public boolean execute() {
        this.loadImage();
        this.modImage();
        this.outImage();
        
        return false;
    }
    
    public static void main(String arguments) {
        CreateI createI = new CreateI();
        createI.execute();
    }
}
---------------------------------------
これでとりあえず実行できるので、実行結果です。

実行結果)1。
---------------------------------------
loadImage()を実行
modImage()を実行
outImage()を実行
---------------------------------------
ここまでいいでしょうか。
動くと安心です。

 

(何もないよりは、大きな処理の流れが理解できたと思います。)


とはいえ、ただ順番に実行しているだけなので、
まぁいろいろ意味がないというか、制御されている感じがありません。
というか、大枠の時点でpublicのexecute()の戻り値をbooleanにしてる。
それを利用して、またさらに組み替えて、
ひとつひとつのメソッドを確認しながら実行するようにしてみます。
確認というか、前の処理がうまくいったら、次の処理という感じです。

例)3。
---------------------------------------
package sample21;

public class CreateI {
    
    private boolean loadImage() {
        System.out.println("loadImage()を実行");
        return true;
    }
    
    private boolean modImage() {
        System.out.println("modImage()を実行");
        return true;
    }
    private boolean outImage() {
        System.out.println("outImage()を実行");
        return true;
    }

    public boolean execute() {
        if(this.loadImage()) {
            if(this.modImage()) {
                if(this.outImage()) {
                    return true;
                }else {
                    return false;
                }
            }else {
                return false;
            }
        }else {
            return false;
        }
    }
    
    public static void main(String arguments) {
        CreateI createI = new CreateI();
        
        if(createI.execute()) {
            System.out.println("全て正常に実行できた");
        }else {
            System.out.println("なんかしっぱいした");
        }
    }
}

------------------------------------------
制御のかなめはif文です。
みればわかる?ですよね。
というわけで実行結果は以下のようになります。

実行結果)2。
------------------------------------------
loadImage()を実行
modImage()を実行
outImage()を実行
全て正常に実行できた
------------------------------------------
まだ処理を実装していないので、あたりまえなのですが、
if文のelseでないほうを通ってきたのがわかります。
まぁでもこれくらいの制御でしたら、クラスを呼び出す側でもできるので、
そっちで実装するのがみやすいかもしれませんねん。
そっちというのはシェルとか、バッチのことです。

さてさて。
さて読み込みです。

loadImage()を実装します。
といっても、コピペかな。
前に作ったものからえいって感じです。

例)4。
(ながくなるのでメソッドのみ。
といいつつimgはメソッドのそとの変数にしてます。
ほかのメソッドで使用するためです。)
---------------------------------------
    private BufferedImage img = null;
    private boolean loadImage() {
        System.out.println("loadImage()を実行");
        //画像を読み込む。
        try {
            this.img = ImageIO.read(new File("./img.png"));
        } catch (IOException e) {
            System.out.println("画像を読み込めませんでした。");
            return false;
        }
    
        return true;
    }
---------------------------------------
実際のプログラムは1行なので、簡単です。
javaの場合try-catchというのがついてくる?のがみづらいけれど。
本来はこちらでエラー制御すべし、ってことなんでしょうね。
今回は(ずっとかも)おまじないとしてeclipseの機能で、追加してます。
例外がスローされるメソッドを呼ぶと、エラーとしてくれるので、エラーをマウスでクリックすると、
エラーを治すための選択肢を用意してくれます。
今回は、import文を追加しました。add import xxxx というやつです。

まぁ実行してみます。

実行結果)3。
---------------------------------------
loadImage()を実行
画像を読み込めませんでした。
なんかしっぱいした
---------------------------------------
失敗してますね。。。

eclipseの機能でtry-catchを追加した場合、e.printStackTraceというのが実際は追加されているのですが、
これを消していたために細かい情報がわからない形になってますが、
要は、ファイルがみつからないので、読めなかったという感じです。
まぁファイルを用意していないので、あたりまえですが。
というわけでファイルを用意して、実行します。
クラスを作っているプロジェクト(sampleにしています。)に、
img.pngという名前の画像ファイルを用意して実行します。

実行結果)4。
---------------------------------------
loadImage()を実行
modImage()を実行
outImage()を実行
全て正常に実行できた
---------------------------------------
テキストが正常な形に戻りました。
うまくいったと思いましょう。

ここまででももう十分ながいですね。挫折しそうです。
つぎはmodImageです。
処理の内容としては、目(のようなマル)を追加します。
確認の仕方がわからないので、最後の出力まで実行はしません。
残りのふたつのメソッドの中を記述します。
modImage()
outImage()

例)5。
---------------------------------------
    private boolean modImage() {
        System.out.println("modImage()を実行");
        //目をつければキャラクターっぽくなる?
        Graphics2D g = this.img.createGraphics();
        g.setColor(Color.WHITE);
        g.drawString("●", 50, 100);
        g.drawString("●", 100, 100);
        return true;
    }
    private boolean outImage() {
        System.out.println("outImage()を実行");
        // 出力
        try {
            ImageIO.write(this.img, "png", new File("./out.png"));
        } catch (IOException e) {
            System.out.println("画像を出力できませんでした。");
            return false;
        }
        return true;
    }
---------------------------------------
今回は、出力も実装済みなので、実際の絵で確認できますね。

f:id:yo2an:20210930190921p:plain

目が追加されたのわかりますかね


あ。。。小さすぎw

というわけで、次回へ続きます。