簡體   English   中英

使用僅包含非抽象方法的抽象類

[英]use of abstract class containing non-abstract methods only

有一個抽象類僅包含非抽象方法。 現在,我創建另一個擴展抽象類的類。 對於前:

    abstract class Parent{
        void No(){
            System.out.println("abcd");
        }
    }

class Child extends Parent {
}

代替抽象類,我可以創建另一個類。 將上面的類作為摘要有什么用?

我想您想知道的是,在這種情況下,不作抽象有什么區別嗎:

不,它不是 :只要您沒有抽象方法,就可以使用抽象或非抽象類(即使在這種情況下abstract沒有意義)。 但是,如果您有一個抽象方法,則需要將您的類標記為抽象。

沒有任何抽象方法的抽象類有時是設計決策。 例如,可以像這樣實現正則表達式:

public abstract class Regex {
    private Regex(String pattern) { /* do something */ }

    private static class ConcreteRegex {
        private ConcreteRegex(String pattern) {
            super(pattern);
        }
    }

    private static final int MAX_CACHE_SIZE = 100;
    private static Object cacheLock = new Object();
    private static Queue<String> patternq = new LinkedList<>();
    private static Map<String, Regex> cache = new HashMap<>();

    private static Regex checkCache(String pattern) {
        synchronized(cacheLock) {
            return cache.get(pattern);
        }
    }

    private static void insertCache(String pattern, Regex regex) {
        synchronized(cacheLock) {
            patternq.offer(pattern);
            cache.put(pattern, regex);
            while(patternq.size() >= MAX_CACHE_SIZE) {
                String key = patternq.poll();
                cache.remove(key);
            }
        }
    }

    public static Regex compile(String pattern) {
        Regex result = checkCache(pattern);
        if (result == null) {
            Regex compiled = new ConcreteRegex(pattern);
            insertCache(pattern, compiled);
            return compiled;
        }
        return result;
    }

    public static Matcher match(String pattern, String str) {
        Regex result = compile(pattern);
        return result.matches(str);
    }

    // define find, findall, and so on like this
}

那么做所有這些工作有什么意義呢? 好吧,有時使用這些方法來縮短程序會非常方便,而可能有機會提高程序的性能。 通過這樣做,我們需要防止用戶直接調用構造函數。 但是為什么在構造函數內部沒有這些緩存管理呢?

好吧,不建議這樣做(盡管它會編譯),因為您在實例化過程中將實例泄漏出去,這樣就有機會引用部分實例化的對象,這通常被視為危險行為。

當然,在其他情況下,您決定擁有此類“怪異”抽象類,這些類太多了,無法枚舉。

這是真的,如果一個抽象類沒有抽象方法,那么就沒有什么強行阻止想成為從創建一個簡單的子類和實例化它的客戶; 但請記住,我們編寫的代碼不僅要供編譯器閱讀,還要供其他程序員(包括將來的自己)閱讀和理解。 我們不能強行阻止那些程序員陷入困境。 但是我們可以編寫代碼來幫助他們做正確的事。

因此,問題是–在什么情況下,一個類沒有抽象方法,但是仍然沒有辦法直接實例化它?

我想到了幾種可能性,但我僅提及其中一種。

考慮一個類似java.util.List的接口,其中許多方法是可以根據其他方法定義的便捷方法。 特別地,可以根據使用索引的方法來定義使用迭代器的方法,反之亦然。

可以輕松想象一個抽象的List實現,該實現定義了所有這些方法,但是彼此定義 然后,您可以通過將實現的子類化並覆蓋iterator-y方法或index-y方法來輕松實現List

(碰巧的是,這不是JDK采取的方法。JDK提供了兩個抽象實現,即java.util.AbstractListjava.util.AbstractSequentialList ,每個實現都有一些抽象方法供子類填充。我認為JDK的方法比較優越,因為它可以使您更清楚地了解應該執行的操作,並在編譯時出錯,而組合抽象類方法在運行時會生成StackOverflowErrorDRY ,采用了組合抽象類方法。)

我看到的一個優點是您可以防止人們實例化它。

例如,您要制作一個車輛系統。 在父抽象類中,只有一個方法run(){},而不是抽象方法。 您想將其實例化為VW,TOYOTA或Ford,而不是未指定品牌的車輛。 您固有的車輛類別為非抽象類的大眾,豐田或福特。 但是您不能從車輛開始,因為它更像是一種“類型”,而不是您想要制造的東西。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM