S_a_k_Uの日記みたいなDB

~サクゥーと呼ばないで~

protectedとは?

パッケージとサブパッケージとprotected

パッケージ分けた時に、パッケージ間には2種類の関係があるような。

xxx.yyy.zzz.util ユーティリティパッケージ
xxx.yyy.zzz.util.date 日付関連のユーティリティパッケージ
xxx.yyy.zzz.util.string 文字列関連のユーティリティパッケージ
xxx.yyy.zzz.print 印刷パッケージ
xxx.yyy.zzz.print.excel Excel関連の印刷パッケージ
xxx.yyy.zzz.print.pdf PDF関連の印刷パッケージ

というパッケージがあれば、utilとprintは初期に見出され、util.*とprint.*は分析/設計が進む上で登場する感じ。
util.*は、utilのクラス群を分類しているだけ。
print.*は、printに印刷に関する抽象クラス群を配置して、print.excelにはexcelの実装、print.pdfにはPDFの実装を配置している(これも分類と言えば分類だけど…)。
例えば、printがutilに依存していたとしても、(継承は別として)protecedなスコープで参照することはなく、あくまでインターフェースあるいはpublicなスコープで参照する。
ところがprintとprint.*については、printに抽象化されているクラス群があり、print.excelとprint.pdfからはパッケージとして”継承関係”みたいな関係に見える。そのため、クラスとしては継承していないが、protecedな参照をしたい場合があったりする。
パッケージの「横の関係」と「縦の関係」というのがあるような気がしてならない。

Interfaceとprotected

パッケージ内で継承関係にないクラスでも、インターフェースを介してアクセスする場合で「publicじゃないんだけどなぁ」という場合があった。
その時は、クラスに求められる「publicな振る舞い」と「protectedな振る舞い」は、そもそも役割が違うってことで”異なるインターフェース”として定義するべきだ、と解釈してみた。
多分「publicな振る舞い」は設計/分析レベルで見出すメソッド、「protectedな振る舞い」は実装に近い設計レベルで見出したメソッドという感じがしてる。


そんな自分と同じような疑問を持った方の質問とその議論。
@IT > interface のメソッドは、なぜ protected にできないのでしょうか?
@IT > class or interface ?


試してみたところ、アクセスレベルを指定しないInterfaceだと、少なくともパッケージ内でのみのインターフェースという形で定義できる。

interface NoSpecifiedInterface {
    void noSpecifiedProcess();
}

だったら、protetedと指定できてもいいんじゃね?と思ってみたりw

インナーインターフェース?

インナークラスがあるんだったら、インナーインターフェースもできるかな?と思ったら、やっぱできるんだ。

package jp.saku.test;

public class TestAccessLevel {
    
    public TestAccessLevel() {
        super();
    }
    
    public void proccess() {
        
        NoSpecifiedInterface noSpecifiedClass = createNoSpecified();
        noSpecifiedClass.noSpecifiedProcess();
        
        PrivateInterface privateClass = createPrivate();
        privateClass.privateProcess();
        
        ProctectedInterface proctectedClass = createProtected();
        proctectedClass.protectedProcess();
        
        PublicInterface publicClass = createPublic();
        publicClass.publicProcess();
        
    }
    
    public NoSpecifiedInterface createNoSpecified() {
        return new NoSpecifiedClass();
    }
    public PrivateInterface createPrivate() {
        return new PrivateClass();
    }
    public ProctectedInterface createProtected() {
        return new ProctectedClass();
    }
    public PublicInterface createPublic() {
        return new PublicClass();
    }
    
    class NoSpecifiedClass implements NoSpecifiedInterface {
        public NoSpecifiedClass() {
            super();
        }
        public void noSpecifiedProcess() {
        }
    }
    private class PrivateClass implements PrivateInterface {
        public PrivateClass() {
            super();
        }
        public void privateProcess() {
        }
    }
    protected class ProctectedClass implements ProctectedInterface {
        public ProctectedClass() {
            super();
        }
        public void protectedProcess() {
        }
    }
    public class PublicClass implements PublicInterface {
        public PublicClass() {
            super();
        }
        public void publicProcess() {
        }
    }
    
    interface NoSpecifiedInterface {
        public void noSpecifiedProcess();
    }
    private interface PrivateInterface {
        public void privateProcess();
    }
    protected interface ProctectedInterface {
        public void protectedProcess();
    }
    public interface PublicInterface {
        public void publicProcess();
    }
    
}

このTestAccessLevelを継承したクラスからの参照だと

package jp.saku.test;

// import文が不要

public class TestAccessLevelExtend extends TestAccessLevel {
    public TestAccessLevelExtend() {
        super();
    }
    public void proccess() {
        
        NoSpecifiedInterface noSpecifiedClass = createNoSpecified();
        noSpecifiedClass.noSpecifiedProcess();

        // PrivateInterfaceが参照できない
        //PrivateInterface privateClass = new TestAccessLevelOtherPackage().createPrivate();
        //privateClass.privateProcess();
        
        ProctectedInterface proctectedClass = createProtected();
        proctectedClass.protectedProcess();
        
        PublicInterface publicClass = createPublic();
        publicClass.publicProcess();
        
    }
}

このTestAccessLevelと同じパッケージのクラスからの参照だと、

package jp.saku.test;

import jp.saku.test.TestAccessLevel.NoSpecifiedInterface;
import jp.saku.test.TestAccessLevel.ProctectedInterface;
import jp.saku.test.TestAccessLevel.PublicInterface;

public class TestAccessLevelRef {
    public TestAccessLevelRef() {
        super();
    }
    public void proccess() {
        
        NoSpecifiedInterface noSpecifiedClass = new TestAccessLevel().createNoSpecified();
        noSpecifiedClass.noSpecifiedProcess();

        // PrivateInterfaceが参照できない
        //PrivateInterface privateClass = new TestAccessLevelOtherPackage().createPrivate();
        //privateClass.privateProcess();
        
        ProctectedInterface proctectedClass = new TestAccessLevel().createProtected();
        proctectedClass.protectedProcess();
        
        PublicInterface publicClass = new TestAccessLevel().createPublic();
        publicClass.publicProcess();
        
    }
}

このTestAccessLevelと別のパッケージのクラスからの参照だと、

package jp.saku.test.test;

import jp.saku.test.TestAccessLevel;
import jp.saku.test.TestAccessLevel.PublicInterface;

public class TestAccessLevelOtherPackage {
    
    public TestAccessLevelOtherPackage() {
        super();
    }
    
    public void proccess() {
        
        // NoSpecifiedInterfaceが参照できない
        //NoSpecifiedInterface noSpecifiedClass = new TestAccessLevel().createNoSpecified();
        //noSpecifiedClass.noSpecifiedProcess();

        // PrivateInterfaceが参照できない
        //PrivateInterface privateClass = new TestAccessLevelOtherPackage().createPrivate();
        //privateClass.privateProcess();
        
        // ProctectedInterfaceが参照できない
        //ProctectedInterface proctectedClass = new TestAccessLevel().createProtected();
        //proctectedClass.protectedProcess();
        
        PublicInterface publicClass = new TestAccessLevel().createPublic();
        publicClass.publicProcess();
        
    }
    
}