Если вы используете Java 9+ , вы можете просто использовать Optional.or
:
return func1().or(() -> func2());
В Java 8 , вам может понадобиться создать новый Опциональный из результатов (используйте orElseGet
, чтобы избежать нетерпеливого выполнения):
return Optional.ofNullable(func1().orElseGet(() -> func2().orElse(null)));
Корректный способ сделать это должно иметь переменную только в базовом классе. Поскольку производный класс знает, что должен иметь динамический тип MyVar
, это полностью разумно:
class MyClass : public MyBase
{
public:
MyClass(MyVar* v) : MyBase(v) {}
MyVar* GetVar() { return static_cast<MyVar*>(MyBase::GetVar()); }
}
Так как MyVar получен из MyVarBase, различных типов возврата GetVar
все еще работал бы, если бы GetVar был виртуальным (как имеет место здесь). Обратите внимание, что с тем методом, не должно быть никакой функции в MyBase
это может сбросить указатель на что-то другое, очевидно.
Отметьте это static_cast
правильный бросок в этом случае. Используя dynamic_cast
, как предложено одним комментатором, скажет читателям и пользователям GetVar это MyBase::GetVar()
мог возвратить указатель на объект не типа MyVar. Но это не отражает наше намерение, поскольку Вы только когда-либо передаете MyVar. Быть последовательным - самая важная вещь в разработке программного обеспечения. То, что Вы могли сделать, должно утверждать, что это является непустым. Это прервется во времени выполнения с сообщением об ошибке в сборках отладки Вашего проекта:
MyVar* GetVar() {
assert(dynamic_cast<MyVar*>(MyBase::GetVar()) != 0);
return static_cast<MyVar*>(MyBase::GetVar());
}
Не зная больше контекста, трудно сказать наверняка, но я пересмотрел бы, нужна ли Вам эта иерархия классов во-первых. Вам действительно нужны классы MyVarBase и MyBase? Вам мог сойти с рук состав вместо наследования? Возможно, Вам не нужна иерархия класса вообще при шаблонной обработке функций и классов, которые работают с вышеупомянутыми классами. Возможно, CRTP может помочь также. Существует много альтернатив использованию виртуальных функций (и в некоторой степени, наследование в целом) в C++.
Так или иначе Ваше собственное предложенное решение, конечно, не должно пропускать память (так как это не выделяет никого), и не повредил бы конструктора копии по умолчанию ни один (так как это просто выполняет мудрую участником копию. Теперь у Вас просто есть дополнительный участник в производном классе, но это копируется также). Конечно, Вы получаете дополнительную проблему хранения этих двух переменных в синхронизации, таким образом, мне все еще не нравится то решение очень.
С другой стороны, Вы можете удалять переменную из базового класса. Сделайте GetVar () функцией чистый виртуальный, таким образом, это только реализовано в производных классах, которые могут определить членскую переменную всегда, им нравится.
Я думаю, что Ваше упоминание о шаблонах может быть хорошим вариантом, таким образом, что-то как:
class MyVarBase
{
};
class MyVar : public MyVarBase
{
int Foo();
};
template <class T> class MyBase
{
public:
MyBase(T* v) : m_var(v) {}
T* GetVar() { return m_var; }
private:
T* m_var;
};
class MyClass : public MyBase<MyVar>
{
public:
MyClass(MyVar* v) : MyBase(v) {}
};
Однако это зависело бы, на каких классах можно на самом деле измениться. Кроме того, определение 'MyClass' могло быть избыточным, если оно не имеет других участников свыше класса MyBase.