Все это хорошие ответы. Я хотел бы добавить пример выполнения при передаче объектов по значению vs по ссылке:
#include <iostream>
using namespace std;
// Base class
class A {
public:
A() {}
A(const A& a) {
cout << "'A' copy constructor" << endl;
}
virtual void run() const { cout << "I am an 'A'" << endl; }
};
// Derived class
class B: public A {
public:
B():A() {}
B(const B& a):A(a) {
cout << "'B' copy constructor" << endl;
}
virtual void run() const { cout << "I am a 'B'" << endl; }
};
void g(const A & a) {
a.run();
}
void h(const A a) {
a.run();
}
int main() {
cout << "Call by reference" << endl;
g(B());
cout << endl << "Call by copy" << endl;
h(B());
}
Выход:
Call by reference
I am a 'B'
Call by copy
'A' copy constructor
I am an 'A'
Когда вы изменяете определение интерфейса на
interface IReadOnlyFoo
{
string Value { get; }
}
interface IReadWriteFoo
{
string Value { get; set; }
}
class BasicFoo : IFoo, IReadOnlyFoo
{
public string Value { get; set; }
}
, оно должно работать.
Все, что вам нужно изменить в своем коде, - это добавить геттер к свойству Value
в интерфейсе IFoo
.
Семантически говоря, IFoo
- это особый вид IReadOnlyFoo
, который добавляет еще одну возможность к своему базовому типу (установщик свойства Value
).
Это точное определение наследования в объектно-ориентированном программировании - дочерний тип является более конкретной версией своего базового типа и добавляет к нему возможности.
interface IReadOnlyFoo
{
string Value { get; }
}
interface IFoo : IReadOnlyFoo
{
new string Value { get; set; }
}
class BasicFoo : IFoo
{
public string Value { get; set; }
}
Этот код является абсолютно действительным и даст вам именно то, что вы ищете.
Таким образом, если у вас есть ссылка типа IReadOnlyFoo
на экземпляр BasicFoo
, свойство Value
действительно доступно только для чтения, но если ваш ссылочный тип - IFoo
, это свойство чтения / записи. [ 1115]
При реализации интерфейса два члена будут объединены, так как у вас нет метода get в IFoo.Value.
interface IReadOnlyFoo
{
string Value { get; }
}
interface IFoo : IReadOnlyFoo
{
new string Value { set; }
}
class BasicFoo : IFoo
{
public string Value { get; set; }
}
Пока вы используете неявные реализации для интерфейсов, они будут вести себя так, как вы и предполагали. с другой стороны, если вы хотите иметь два разных поведения для членов интерфейса, то вы хотите использовать явные реализации. Вы можете найти пример здесь
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/how-to-explicitly-implement-members-of -Два-интерфейсы