質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.49%

  • Java

    14057questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

javaクラスの初歩的な質問

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 533

uer03108

score 93

下記の様なクラスがあった場合、javaならではの(?)スマートな書き方ってあるのでしょうか。
funcPre関数の重複を簡略化できるのかなと言う質問になります。

class Sample{

    public void funcA(int n){
        funcPre();
        //処理
    }

    public void funcB(int n){
        funcPre();
        //処理
    }

    public void funcC(int n, int m){
        funcPre();
        //処理
    }

    public void funcD(int n){
        //処理
    }

    //前処理
    private void funcPre(){
        //処理
    }
}

追記
多くのご回答有難うございました。
勉強になります。

記述が重複する部分をprivate関数に置き換えていると、今度は関連性のないprivate関数が増えていって、その部分が読みにくくなると思って、質問させて頂きました。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • mts10806

    2017/09/20 14:47

    そうしたい目的を具体的に記載いただけると助かります。

    キャンセル

  • coco_bauer

    2017/09/20 16:11

    funcPre関数で処理されるコードは、funcPre関数の定義の中にだけ存在するので重複(同じ処理をするコードが複数の関数の中に出現)はありません。その意味でSlimなコードになっています。

    キャンセル

  • swordone

    2017/09/21 00:47

    構成を考え直すことも視野に入れるべきでは?具体的にどのような処理になるのでしょうか?

    キャンセル

回答 5

+1

よくわかりませんが、たとえばこういうのですか (未検証)。

class Sample {
    class Action {
        public void exec() {
            funcPre();
            doExec();
        }
        protected void funcPre(){
            //処理 
        }
        abstract public void doExec();

    }
    class ActionA extends Action {
        public void doExec() {
             // 処理
        };
        public setArgs(int n) {
             this.n = n;
             return this;
        }
    }

    public void funcA(int n){
        return new ActionA().setArgs(n).exec();
    }

    public void funcB(int n){
        return new ActionB().setArgs(n).exec();
    }

    public void funcC(int n, int m){
        return new ActionC().setArgs(n, m).exec();
    }

    public void funcD(int n){
        //処理
    }
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/21 14:04

    有難うございました。
    こういうのです。
    クラスを書けばよいのですね。
    助かりました。

    キャンセル

+1

目的に沿ったものではないかもしれませんがコンストラクタで呼ぶのはどうでしょうか。

class Sample{

    public Sample(){
        funcPre();
    }

    public void funcA(int n){
        //処理
    }

    public void funcB(int n){
        //処理
    }

    public void funcC(int n, int m){
        //処理
    }

    public void funcD(int n){
        //処理
    }

    //前処理
    private void funcPre(){
        //処理
    }
}


funcD()を使う場合にもfuncPre()が呼び出されてしまうという点が許容できるのであれば ですが。。。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

public abstract class Sample {

    private void preFunc(){
        //処理
    }

    protected abstract void func();

    public void do() {
        preFunc();
        func();
    }
}

class SampleA extends Sample {
    private int n;

    public SampleA(int n) {
        this.n = n;
    }

    @Override
    protected void func() {
        //処理
    }   
}

class SampleB extends Sample {
    private int n;

    public SampleB(int n) {
        this.n = n;
    }

    @Override
    protected void func() {
        //処理
    }   
}

class SampleC extends Sample {
    private int n;
    private int m;

    public SampleC(int n, int m) {
        this.n = n;
        this.m = m;
    }

    @Override
    protected void func() {
        //処理
    }   
}

class SampleD extends Sample {
    private int n;

    public SampleD(int n) {
        this.n = n;
    }

    @Override
    protected void func() {
        //処理
    }

    @Override
    public void do() {
        func();
    }
}

public class Main {
    public static void main(String[] args) {
        Sample sampleA = new SampleA(1);
        sampleA.do();

        Sample sampleB = new SampleB(1);
        sampleB.do();

        Sample sampleC = new SampleC(1,2);
        sampleC.do();

        Sample sampleD = new SampleD(1);
        sampleD.do();
    }
}


す、すまーと

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

もっとコードが具体的になれば違った回答もあるかもしれませんが、質問文にあるコードで十分簡潔だと考えてよいです。

記述が重複する部分をprivate関数に置き換えていると、今度は関連性のないprivate関数が増えていって、その部分が読みにくくなると思って、質問させて頂きました。

private メソッドが互いに関連性がない(=独立している)方がよりよいコードと言えます。
public メソッドから利用する場合に private メソッドの呼び出し順やフィールドの状態に注意しなければならないとすると、より悪い状況におちいっています。

private メソッドが単純に多い場合は別のクラス(=責務)へと切り出せないか検討するとよいでしょう。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/20 20:44

    「別のクラス(=責務)へと切り出せないか検討」の雰囲気的を感じます

    キャンセル

checkベストアンサー

0

Javaならでは…
Javaの標準機能だけでは無理なのですが、スマートな書き方であれば、AspectJ5によるアノテーション記法でしょうか。

以下のサンプルコードを動かすにはaspectjrtとaspectjweaverのライブラリが必要なので、少し難しいです。

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

// @Aspectを書いたクラスはAspectJのコンパイル対象クラスとなり、@Beforeなどが使えるようになる
@Aspect
public class Sample {

    public void funcA(int n) {
        //処理
        System.out.println("funcA " + n);
    }

    public void funcB(int n) {
        //処理
        System.out.println("funcB " + n);
    }

    public void funcC(int n, int m) {
        //処理
        System.out.println("funcC " + n + " " + m);
    }

    public void funcD(int n) {
        //処理
        System.out.println("funcD " + n);
    }

    // @Beforeの中に条件を書くと、条件に当てはまるメソッドの処理の前に呼び出してくれる
    // callは「そのメソッドを呼び出したとき」という条件
    // 条件の書き方はAspectJの仕様を参照してください
    // 以下の条件の場合、funcA、またはfuncB、またはfuncCのときだけ実行される
    @Before("call(void funcA(int))"
            + " || call(void funcB(int))"
            + " || call(void funcC(int, int))")
    public void funcPre(JoinPoint joinPoint) {
        // JoinPointは呼び出し元などの情報が入っている

        System.out.println("funcPre");
        // このメソッド内でthisと書いても、funcAを呼んでいるインスタンスとは別物なので注意
        // 以下のように呼び出し元インスタンスはgetTargetで得る
        // Sample sample = (Sample) joinPoint.getTarget();
    }

    public static void main(String[] args) {
        Sample m = new Sample();
        m.funcA(0);
        m.funcB(1);
        m.funcC(2, 3);
        m.funcD(4);
    }
}

Mavenを使えばAspectJを使ったコードを簡単にビルドできます。mavenを利用した場合のpom.xmlの参考です。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>example</groupId>
    <artifactId>aspectj</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>

        <aspectj-maven-plugin.version>1.10</aspectj-maven-plugin.version>
        <aspectj.version>1.8.10</aspectj.version>
    </properties>


    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>        
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>${aspectj-maven-plugin.version}</version>
                <configuration>
                    <complianceLevel>${maven.compiler.source}</complianceLevel>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                </configuration>
                <executions>
                    <execution>
                        <phase>process-sources</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj.version}</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
    </dependencies>

</project>

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/21 13:53

    回答有難うございました。
    便利なものがあるんですね。
    これは@Beforeの関数に戻り値も設定できるのでしょうか。
    グローバル変数を使用するとか??

    キャンセル

  • 2017/09/21 14:19

    えっと、funcPreでなにか結果を返したいということでしょうか?

    キャンセル

  • 2017/09/21 14:30

    はい。
    List<Object> funcPre( )
    などですが。

    ・前処理の値を取得
    ・関数内で処理(関数によって異なる)
    ・処理結果を後処理

    といった関数を簡潔に書く方法を考えておりました。

    前処理と後処理をprivate関数にしています。

    private関数がゴチャゴチャ・・・と言った感じです。
    複数ファイルに分けた方が良いかもしれません。

    キャンセル

  • 2017/09/21 14:33

    重ね重ね有難うございます。

    キャンセル

  • 2017/09/21 15:15

    一時変数を受け取らなければならない以上、省略することはできないかと思います…メンバ変数に一時的にキープしておくことは可能ですが、スレッドセーフなどを気にする必要が出てきます。とりあえず、メンバ変数に一時的に記憶する場合の処理を追記します。

    キャンセル

  • 2017/09/21 15:17

    と思ったのですが、まず具体的にやりたいことをコードにして例示してもらえませんか。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 受付中

    明解Java入門編演習9−3

    この演習はDayクラスを使わずに行う演習なのでしょうか? Dayクラスを使うのなら、銀行口座クラスにtoStringメソッドを作る理由が分かりません。 また、もしDayクラスを

  • 解決済

    クラス型配列のフィールドにアクセスしたいです。

    前提・実現したいこと サイコロが同じかどうかをチェックするプログラムです。 サイコロがn個与えられ、サイコロ各面に任意の数字が割り振られます。 サイコロDiceは_d[6]を

  • 解決済

    呼び出すメソッドで戻り値を変えたい

    CalendarClassを使って、1年分の日付を取得するPGを作ってます。 メソッドに返す戻り値を変える良い方法はありませんか。 例えば、mainClassでthisMo

  • 解決済

    サブクラスからスーパクラスへのフィールド変数への代入

    サブクラスから、スーパクラスのフィールド変数に値を代入することは可能でしょうか。 具体的なコーディングの見本などありましたら、助かります。 よろしくお願いします。

  • 解決済

    jmockit1.3でメソッドのみをモック化したい

    例えば、AClassのメソッドであるAmethodのみをモック化したい場合、過去のバージョンでは、以下のような指定で実現できました。 @Mocked("Amethod") A

  • 解決済

    Java 子クラスを介して親クラスのメソッドにアクセスする処理について

    質問 Java 継承関係にあるクラスの扱いについて 下記のように、子クラスに個別の処理を、 親クラスに共通の処理を実装した際に、メインのクラスから子クラスのmethodAを介し

  • 受付中

    javaで宝探しゲームを作る

    前提・実現したいこと javaを使って簡単な宝探しゲームを作成しようと考えています。 キーボードから座標を入力(例えば3-a, 5-cなど)して、下記の表が宝箱の有無によって表

  • 解決済

    javaクラスの初歩的な質問

    下記の様な簡単な抽象クラスを作りました。 文字列に接頭語、接尾語を追加するクラスになります。 この例では、抽象関数doExecの戻り値は文字列型ですが、違う変数型でも返したい場

同じタグがついた質問を見る

  • Java

    14057questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。