Если вы используете C ++ 17, вы можете сделать следующее (скомпилировано с помощью команды g++ -std=c++17 -Wall -Wpedantic main.cc
, используя g++
версию 7.3.0 в Debian):
#include <iostream>
#include <cstdint>
#include <climits>
#include <type_traits>
template<typename InputType>
constexpr auto ConcatenateBits(InputType highPart, InputType lowPart) {
constexpr bool is_uint8 = std::is_same<InputType, uint8_t>::value;
constexpr bool is_uint16 = std::is_same<InputType, uint16_t>::value;
constexpr bool is_uint32 = std::is_same<InputType, uint32_t>::value;
static_assert(is_uint8 || is_uint16 || is_uint32,
"Input type to ConcatenateBits must be uint{8,16,32}_t.");
if constexpr (is_uint8) {
uint16_t output = lowPart;
output |= (static_cast<uint16_t>(highPart) << (sizeof(InputType) * CHAR_BIT));
return output;
} else if constexpr (is_uint16) {
uint32_t output = lowPart;
output |= (static_cast<uint32_t>(highPart) << (sizeof(InputType) * CHAR_BIT));
return output;
} else {
uint64_t output = lowPart;
output |= (static_cast<uint64_t>(highPart) << (sizeof(InputType) * CHAR_BIT));
return output;
}
}
int main() {
uint16_t explicitly_typed_variable = 1;
std::cout << ConcatenateBits(explicitly_typed_variable, explicitly_typed_variable) << "\n";
std::cout << ConcatenateBits<uint8_t>(1, 2) << "\n";
}
С выводом:
65537
258
Это невозможно в Java. Существование статических
методов не может быть принудительным; ни с помощью аннотации
, ни с помощью интерфейса
.
Мое решение состояло в том, чтобы использовать IoC определенным образом: я создал фабричный класс для синглтонов. Это сохранит одиночные объекты на карте. Ключом будет класс. Таким образом, я мог бы сказать:
A singleton = Factory.create (A.class);
Основное преимущество этого дизайна: я могу создать метод Factory.replace ()
, в котором тестовые примеры могут переопределить синглтоны.
Вы не можете выразить, что дочерние классы имеют определенные статические методы.
На самом деле в этом нет необходимости, поскольку статические методы будут вызываться только непосредственно в дочерних классах ( A.init ()
и A.getInstance ()
в вашем примере) и никогда через ссылку на базовый класс (т. е. статические методы не поддерживают полиморфизм ).
Почему бы вам не пройти весь путь и не передать вашей фабрике (в базовом классе) параметр, указывающий, какой подкласс вы хотите вернуть. У такого способа есть много преимуществ и мало недостатков.
То, как вы это пытаетесь сделать, не имеет большого смысла, поскольку статические методы не работают с наследованием точно так же, как обычные методы.
Распространенным способом решения проблемы добавления семантики синглтона к классу, для которого может быть неудобно правильное добавление семантики, является реализация функциональности синглтона в классе-оболочке. Например:
public class UsefulThing {
}
public final class SingletonOfUsefulThing {
private static UsefulThing instance;
private SingletonOfUsefulThing() {}
public UsefulThing getInstance() {
if (instance == null) {
instance = new UsefulThing();
}
return instance;
}
}
Это позволяет вам предоставить некоторые из основных преимуществ синглтона классу без некоторых последствий, которые реализация семантики синглтона в классе напрямую вынуждает вас иметь дело и дает некоторое пространство для изменения конкретного типа класс, который вы представляете как одноэлементный (например, используя фабрику для создания экземпляра вместо new
.