[英]Is instantiating an instance of an abstract class a runtime or compilation error?
[英]Can I make a method in an abstract class which constructs an instance for the instantiating class?
我有兩個類擴展了抽象模型。 這兩個類都實現了一個稱為instance()的方法,以基本上確保任何時候該類只有一個實例。 兩個類的instance()的結構完全相同,因此我認為將其上移到抽象類的層次很好。 但是,該方法調用實例化類的默認構造函數。 是否可以從抽象類中調用此構造函數? 如果可以,怎么辦? 還有什么其他方法可以推廣此方法?
我有一個模型的抽象類,看起來像
public abstract class Models{
public List<Model> models = new ArrayList<Model>();
/** load the different models, with the models with pre-trained model*/
public abstract void load();
}
還有兩個像這樣的講解班
public class PageLanguageModels extends Models {
/** ensure we only call one of them */
protected static PageLanguageModels _instance = null;
static Logger logger = Logger.getLogger(ProductLanguageModels.class.getName());
public static synchronized PageLanguageModels instance() {
if (_instance == null) {
try {
_instance = new PageLanguageModels();
_instance.load();
} catch (Exception e) {
logger.log(Level.SEVERE, "Couldn't load language models.", e);
}
}
return _instance;
}
/** load the different models, with the models with pre-trained model*/
@Override
public void load() {
models.clear();
models.add(new BOWModel());
}
}
public class ProductLanguageModels extends Models {
/** ensure we only call one of them */
protected static ProductLanguageModels _instance = null;
static Logger logger = Logger.getLogger(ProductLanguageModels.class.getName());
public static synchronized ProductLanguageModels instance() {
if (_instance == null) {
try {
_instance = new ProductLanguageModels();
_instance.load();
} catch (Exception e) {
logger.log(Level.SEVERE, "Couldn't load language models.", e);
}
}
return _instance;
}
/** load the different models, with the models with pre-trained model*/
@Override
public void load() {
models.clear();
models.add(new Word2VecModel());
}
}
我曾嘗試使用工廠方法模式,但這不起作用,因為實例是靜態方法,並且不能從靜態方法調用抽象工廠方法。
無法從Models類型靜態引用非靜態方法makeModels()
public abstract class Models{
/** load the different models, with the models with pre-trained model*/
public abstract void load();
//Factory method
public abstract Models makeModels();
// Instance code moved up from instanciating classes
protected static Models _instance = null;
static Logger logger = Logger.getLogger(Models.class.getName());
public static synchronized Models instance() {
if (_instance == null) {
try {
_instance = makeModels();
_instance.load();
} catch (Exception e) {
logger.log(Level.SEVERE, "Couldn't load language models.", e);
}
}
return _instance;
}
}
由於其靜態性質和與類型擦除有關的問題,我不認為您可以將所有實例化邏輯都移到父類中,但是您一定可以組織代碼以使其可重用。 我為您編寫了一個簡單的復制/粘貼示例,僅着重於實例化部分,對設計進行了一些更改,因此省略了一些屬性和日志代碼:
接口
public interface Models {
void load();
}
抽象實現
public abstract class BaseModels implements Models {
protected static <T extends Models> T instance(Class<T> type, T candidate) {
if (candidate == null) {
try {
candidate = type.newInstance();
candidate.load();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
return candidate;
}
}
具體實施
public class HeroModels extends BaseModels {
static HeroModels instance;
public static HeroModels instance() {
instance = instance(HeroModels.class, instance);
return instance;
}
@Override
public void load() {
System.out.println("Loading HeroModels...");
}
}
一個簡單的測試用例
public class TestDrive {
@Test
public void testEquality() {
HeroModels a1 = HeroModels.instance();
HeroModels a2 = HeroModels.instance();
Assert.assertEquals(a1, a2);
System.out.println("a1: " + a1);
System.out.println("a2: " + a2);
}
}
測試用例輸出
Loading HeroModels... a1: HeroModels@736e9adb a2: HeroModels@736e9adb
從輸出中,您可以看到HeroModels
類僅被加載一次。 使BaseModel
類中的instance(...)
方法受到保護,以明確表明它打算由子級使用,子級可能具有自己的靜態實例屬性。
是的,但是您可能希望將其提取到單獨的類中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.