У меня есть вопрос относительно наследования и проектирования пользовательского интерфейса.Наследование и 2 типа интерфейса
У меня есть class KeyboardKey
, которая представляет собой отдельные клавиши клавиатуры, например, Q, W, E, R, ... и т.д.
У меня есть class Keyboard
, который содержит векторclass Keyboardkey
. [Важно!]
Я использую SFML, и поэтому каждый раз, когда событие генерируется из цикла событий, оно отправляется классу клавиатуры. Затем этот класс управляет этим событием до соответствующего ключа.
Кроме того, у меня есть class SynthesizerKey
, который наследует от KeyboardKey
. В дополнение к обычным ключевым словам, таким как «включен ключ», «нажата клавиша», этот класс содержит данные и функции для обработки генерации звукового сигнала sin. Переменные включают амплитуду и текущую фазу волны sin.
Я сейчас собираюсь создать class SynthesizerKeyboard
. Я собирался скопировать и вставить весь код из class Keyboard
в этот класс, однако это не очень хорошая практика программирования, так как код дублируется!
Основная проблема, которую я имею, заключается в том, что SynthesizerKeyboard
содержит функцию для генерации последовательности выборок, которые должны храниться в буфере. Чтобы сгенерировать образцы, цикл повторяется по каждому KeyboardKey
и проверяет, нажата ли она. Если это так, тогда мы должны сгенерировать образец, соответствующий этой ноте/частоте клавиш.
Однако, поскольку вектор содержит class KeyboardKey
и неclass SynthesizerKey
не имеют переменные для фазы и амплитуды волн греха в качестве данных членов элементов вектора.
Я думаю, что мне, возможно, придется выполнять так называемый «рефакторинг» [?] И отделять части «sin wave» от SynthesizerKey
от KeyboardKey
частей. Другими словами, я выбрасываю класс SynthesizerKey
и имею класс Synthesizer
и класс KeyboardKey
, отдельно. Затем у меня есть вектор Synthesizer
в class SynthesizerKeyboard
в дополнение к вектору KeyboardKey
в class Keyboard
, к которому у меня есть доступ в SynthesizerKeyboard
через наследование.
Однако это менее элегантно. Есть ли другой способ?
Ниже приведен код, который может помочь читателю лучше понять quesiton.
SynthesizerKeyboard
class SynthesizerKeyboard : public Keyboard
{
public:
SynthesizerKeyboard(const sf::Font& sf_font)
: Keyboard(sf_font)
{
}
double Sample() const
{
for(std::vector<KeyboardKey>::iterator it = m_keyboardkey.begin()
it != m_keyboardkey.end(); ++ it)
{
if(it->IsKeyPressed())
{
it->Sample();
}
}
}
void GenerateBufferSamples(std::vector<sf::Int16> buffer)
{
for(std::size_t i = 0; i < buffer.size(); ++ i)
{
buffer[i] = Sample();
}
}
};
SynthesizerKey
class SynthesizerKey : public KeyboardKey
{
protected:
AbstractOscillator *m_abstractoscillator;
public:
double Sample() const
{
return m_abstractoscillator->Sample();
}
};
Клавиатура
class Keyboard
{
protected:
std::vector<KeyboardKey> m_keyboardkey;
public:
Keyboard(const sf::Font& sf_font)
void Draw(sf::RenderWindow& window)
void Event(const sf::Event& event)
{
for(std::vector<KeyboardKey>::iterator it = m_keyboardkey.begin();
it != m_keyboardkey.end(); ++ it)
{
(*it).Event(event);
}
}
bool IsKeyPressed(const sf::Keyboard::Key& sf_key)
{
for(std::vector<KeyboardKey>::iterator it = m_keyboardkey.begin();
it != m_keyboardkey.end(); ++ it)
{
if((*it).Key() == sf_key)
{
return (*it).IsKeyPressed();
}
}
}
};
KeyboardKey
class KeyboardKey
{
protected:
KeyState m_keystate;
sf::Color m_pressed_color;
sf::Color m_release_color;
sf::Text m_sf_text;
sf::Keyboard::Key m_sf_keyboard_key;
sf::RectangleShape m_sf_rectangle;
public:
KeyboardKey(const sf::Keyboard::Key& sf_keyboard_key, const std::string& text, const sf::Font& sf_font,
const double position_x, const double position_y)
void Draw(sf::RenderWindow& window)
void Event(const sf::Event& event)
bool IsKeyPressed()
};
вы можете полочки кода, который вы беспокоитесь о дублировании в «AbstractKeyboard» в комплекте с функциями чистой виртуальной специализации, реализованными «наследниками» AbstractKeyboard, которые вызывается из «AbstractKeyboard», когда требуется, например, «поведение, зависящее от Moog».'AbstractKeyboard' также содержит' std :: vector> ', так что' KeyboardKey' или соответствующие подклассы могут содержаться без проблем управления памятью. –
user4581301
@ user4581301 Я не уверен, что я полностью понимаю ваше предложение в деталях ... не могли бы вы объяснить это дальше мне или, возможно, добавить предлагаемый ответ, возможно, с примерами? – user3728501