In effetti ciò che stai cercando è un modo per presentare un'entità immutabile attraverso la sua API pubblica, ma consentire comunque lo stato mutabile come dettaglio di implementazione dietro le quinte.
A volte questa è una scelta di design valida, ma non usare è leggermente. Soprattutto, dal momento che prometti l'immutabilità del chiamante, assicurati che dopo che l'entità è stata creata, non cambierà mai il suo stato visibile pubblicamente .
Posso pensare a due situazioni in cui tale mutabilità nascosta è un approccio valido.
- Per una valutazione lenta come nel tuo esempio.
- Per lo stato interno che deve essere modificabile a fini amministrativi / di pulizia. Un esempio diretto consiste nell'acquisire e rilasciare un mutex (cioè modificarne lo stato) per leggere una variabile in modo thread-safe.
Non posso darti una panoramica su come "la mutabilità interna" è supportata in molti linguaggi perché so principalmente C ++ e Python, e sto iniziando a dilettarmi un po 'in Rust.
Nella costanza Python nel senso della tua domanda non esiste affatto, quindi non è necessario un supporto speciale per la mutabilità interna.
In Rust Cell e RefCell sembrano essere le cose da cercare .
In C ++ la lingua fornisce la parola chiave mutable
(e talvolta un argomento può essere fatto per const_cast
):
class Entity
{
public:
explicit Entity(int i): m_i_might_be_const(i) {}
int get_mutable() const
{
++m_i_can_change;
return m_i_can_change;
}
int get()
{
++m_i_might_be_const;
return m_i_might_be_const;
}
// Fails to compile with a message like:
// "Const member function cannot change object’s state."
int get_error() const
{
++m_i_might_be_const;
return m_i_might_be_const;
}
private:
mutable int m_i_can_change = 0;
int m_i_might_be_const;
}
int main()
{
const Entity e(42);
// Works because m_i_can_change is mutable
auto a = e.get_mutable();
// Fails to compile with a message like:
// "Calling non-const member function on const object e."
auto b = e.get();
}