Здравствуйте, Poul_Ko, Вы писали:
P_K>И вот ещё пример кода для размышления: P_K>
P_K> public interface B
P_K> {
P_K> string Name
P_K> { get; }
P_K> }
P_K> public interface A
P_K> {
P_K> string Name
P_K> { set; }
P_K> }
P_K> internal interface AB : A, B
P_K> {}
P_K> internal class MyClass : AB
P_K> {
P_K> public string _name;
P_K> string A.Name
P_K> {
P_K> set { _name = value; }
P_K> }
P_K> string B.Name
P_K> {
P_K> get { return _name; }
P_K> }
P_K> }
P_K>
P_K>Этот код прекрасно компилируется, хотя, казалось бы, MyClass не содержит реализации AB.
Пример интересный, но не сказать, чтобы здесь понадобилось много размышлений. Интерфейс AB является производным от двух базовых интерфейсов, А и В, но собственных методов не имеет. Поэтому при построении класса, реализующего AB, достаточно реализовать методы A и B.
Здравствуйте, Poul_Ko, Вы писали:
P_K>Вот именно. Чтобы убедиться в этом, попробуйте в классе MyClass сделать explicit-реализацию интерфейса AB.
...
P_K>Этот код прекрасно компилируется, хотя, казалось бы, MyClass не содержит реализации AB.
(Вдогонку) Что здесь самое интересное, так это скрытая опасность. Если попробовать добавить в реализацию модификатор доступа:
public interface B
...
public interface A
...
internal interface AB : A, B
{}
internal class MyClass : AB
{
public string _name;
string A.Name
{
publicset { _name = value; }
}
string B.Name
{
publicget { return _name; }
}
}
Виноват, у меня ошибка в предыдущем сообшении. Конечно, я хотел сказать:
public interface B
...
public interface A
...
internal interface AB : A, B
{}
internal class MyClass : AB
{
public string _name;
publicstring A.Name //так нельзя
{
set { _name = value; }
}
publicstring B.Name //так нельзя
{
get { return _name; }
}
}
С>public interface B
С>...
С>public interface A
С>...
С>internal class MyClass : AB
С>{
С>...
С> publicstring A.Name //так нельзя
С>...
С> publicstring B.Name //так нельзя
С>...
С>
Естественно, так нельзя! При explicit-реализации интерфейса нельзя указывать модификатор доступа.
, у Интерфейса AB есть и геттер и сеттер, как и у базовых интерфейсов, но обращаться через AB к ним нельзя, хотя реализация и get и set присутствует.
N>Там у AB нет ни геттера, ни сеттера. Наследование у интерфейсов работает не так, как у классов. Интерфейс не наследует члены базовых интерфейсов.
Т.е. получается что для интерфейсов никакой vtbl нет? как же тогда происходит связывание с нужной реализацией?
То что MyClass наследуя AB, на самом деле наследует сначала AB потом B это понятно, но если я добавил в AB метод то в vtbl должно быть 2 записи для двух разных функций: для AB.get_Name B.get_Name, но получается что ссылаются они на одну и туже реализацию.
Если в MyClass явно указать что реализация AB.Name, то компилятор ругнется, что не найдена реализация для B.Name, но если этого не указывать, то оба(!) геттера будут сслаться на один и тот же метод!
F>То что MyClass наследуя AB, на самом деле наследует сначала AB потом B это понятно, но если я добавил в AB метод то в vtbl должно быть 2 записи для двух разных функций: для AB.get_Name B.get_Name, но получается что ссылаются они на одну и туже реализацию.
F>Если в MyClass явно указать что реализация AB.Name, то компилятор ругнется, что не найдена реализация для B.Name, но если этого не указывать, то оба(!) геттера будут сслаться на один и тот же метод!
Здравствуйте, Сокрашт, Вы писали:
С>А почему нельзя? (Вообще-то мне известно, почему нельзя, но хотелось бы знать Ваш вариант ответа).
Мне кажется, что разработчики языка сочли такую возможность лишней, так как область видимости таких мемберов всегда однозначно определяется областью видимости интерфейса. Это всего лишь моё предположение, интересно было бы проверить его с помощью Reflector'а...
Глянул в спецификацию, там по этому поводу сказано:
Explicit interface member implementations have different accessibility characteristics than other members. Because explicit interface member implementations are never accessible through their fully qualified name in a method invocation or a property access, they are in a sense private. However, since they can be accessed through an interface instance, they are in a sense also public.
, у Интерфейса AB есть и геттер и сеттер, как и у базовых интерфейсов, но обращаться через AB к ним нельзя, хотя реализация и get и set присутствует.
N>>Там у AB нет ни геттера, ни сеттера. Наследование у интерфейсов работает не так, как у классов. Интерфейс не наследует члены базовых интерфейсов.
F>Т.е. получается что для интерфейсов никакой vtbl нет? как же тогда происходит связывание с нужной реализацией?
F>То что MyClass наследуя AB, на самом деле наследует сначала AB потом B это понятно, но если я добавил в AB метод то в vtbl должно быть 2 записи для двух разных функций: для AB.get_Name B.get_Name, но получается что ссылаются они на одну и туже реализацию.
F>Если в MyClass явно указать что реализация AB.Name, то компилятор ругнется, что не найдена реализация для B.Name, но если этого не указывать, то оба(!) геттера будут сслаться на один и тот же метод!
Здравствуйте, Feral, Вы писали:
F>Т.е. получается что для интерфейсов никакой vtbl нет? как же тогда происходит связывание с нужной реализацией?
То, какой метод данного класса на какой (или какие) методы интерфейсов отображаются, решается на этапе компиляции. Этот процесс описан в Ecma-334, 20.4.2 Interface mapping. Когда вызов метода проиходит через переменную, имеющую интерфейсный тип, то на этапе компиляции, естественно, невозможно определить, в каком классе (или упакованной структуре) находится вызываемый метод. Но, если эта переменная не равна null, то в рантайме можно однозначно определить тип объекта, на который она ссылается, и, соответственно, реализацию метода, который должен быть вызван.
F>То что MyClass наследуя AB, на самом деле наследует сначала AB потом B это понятно, но если я добавил в AB метод то в vtbl должно быть 2 записи для двух разных функций: для AB.get_Name B.get_Name, но получается что ссылаются они на одну и туже реализацию.
Да, на одну.
F>Если в MyClass явно указать что реализация AB.Name, то компилятор ругнется, что не найдена реализация для B.Name, но если этого не указывать, то оба(!) геттера будут сслаться на один и тот же метод!
Да, так и дожно быть. Это описано здесь: Ecma-334, 20.4.2 Interface mapping.