Странная модификация наследования - PullRequest
1 голос
/ 27 октября 2011

Я разработчик .NET и хорошо знаю ООП.Однако недавно я заметил один интересный факт.

System.Data.SqlClient.SqlCommand происходит от System.Data.Common.DbCommand.Последний реализует System.IDbCommand.System.IDbCommand предоставляет свойство Connection, которое является экземпляром IDbConnectionDbCommand Однако это свойство возвращает тип DbConnection.И, наконец, то же свойство в SqlCommand имеет тип SqlConnection

Я пытался выполнить то же самое, однако оно дало ошибку времени компиляции.Как это было достигнуто в примере выше и как я могу воссоздать тот же шаблон?

Мой код (не компилируется):

public interface IFoo { }
public interface IBar 
{
   IFoo TheFoo();
}

public abstract class AbsFoo : IFoo { }
public abstract class AbsBar : IBar 
{
    public abstract AbsFoo TheFoo();
}

public class ConcreteFoo : AbsFoo { }
public class ConcreteBar : AbsBar { }

Ответы [ 3 ]

4 голосов
/ 27 октября 2011

Явная реализация интерфейса - это название игры здесь.Попробуйте это:

public abstract class AbsBar : IBar {
    IFoo IFoo.TheFoo() { return this.TheFoo(); }
    public abstract AbsFoo TheFoo();
}

Вот хорошее руководство по неявной и явной реализации .

2 голосов
/ 28 октября 2011

Я должен сказать, что я думаю, Ричард был немного трудным - его ответ так же хорош, как и Джейсон , в том, что они оба ответили только на половину вопроса, Соедините их вместе, и у вас будет полный ответ.

Чтобы это работало с IDbCommand, DbCommand & SqlCommand, должна быть явная реализация IDbCommandв DbCommand ( ответ Джейсона ) и публичный метод теневого копирования в SqlCommand ( ответ Ричарда ).

Я дам полный "Foo / Bar"пример.

Начните с этих интерфейсов:

public interface IFoo
{
    IBar GetBar();
}

public interface IBar { }

Далее Foo должен обеспечить явную реализацию IFoo, чтобы возвращать Bar, а не IBar, из егособственный GetBar метод:

public abstract class Foo : IFoo
{
    IBar IFoo.GetBar()
    {
        return this.GetBar();
    }

    public Bar GetBar()
    {
        return this.GetBarInner();
    }

    protected abstract Bar GetBarInner();
}

public abstract class Bar : IBar { }

И, наконец, класс SomeFoo должен затенять GetBar, чтобы иметь возможность вернуть SomeFoo экземпляр:

public class SomeFoo : Foo
{
    public new SomeBar GetBar()
    {
        return new SomeBar();
    }

    protected override Bar GetBarInner()
    {
        return this.GetBar();
    }
}

public class SomeBar : Bar { }

Я думаю,Единственная информация, которую Ричард, это то, что, добавив ключевое слово new к затененному методу, вы избавляетесь от ошибки компилятора.

1 голос
/ 28 октября 2011

Соединения в DbCommand и SqlCommand являются просто публичными методами. Было бы предупреждение компилятора, но это разрешено. Ваш код должен быть примерно таким, чтобы он работал как SqlCommand / DbCommand:

    public interface IFoo { }
public abstract class AbsBaseBar
{
    public IFoo TheFoo() { throw new NotImplementedException(); }
}
public class AbsFoo : IFoo { }
public class AbsBar : AbsBaseBar
{
    public AbsFoo TheFoo() { throw new NotImplementedException(); }
}

public class ConcreteFoo : AbsFoo { }
public class ConcreteBar : AbsBar { } 
...