принцип подстановки Лискова и обработка исключений
Он говорит, что производный класс не должен выбрасывать какое-либо исключение, которое не известно базовому классу, я пытаюсь найти, как его работа, в базовом классе я выбрасываю систему.Исключение и в производном я бросаю ArgNullException (). Может кто-нибудь объяснить, это нормально
class b
{
virtual public void foo()
{
try
{
if (true)
throw new System.Exception();
}
catch (Exception ex)
{
Console.WriteLine("in base");
}
}
}
class a : b
{
override public void foo()
{
try
{
if (true)
throw new ArgumentNullException();
}
catch (Exception ex)
{
Console.WriteLine("in dervied");
}
}
}
3 ответа:
class MyClass { public virtual void Foo() { if (true) throw new System.Exception(); } } } class MyDerivedClass : MyClass { public override void Foo() { if (true) throw new ArgumentNullException(); } } } public class Program { public static void Main() { try { // a factory creating the correct // MyClass derived instance var myClass = someFactory.Create(); myClass.Foo(); } catch (Exception) { // will work. } } }
В этом случае вы создаете наименее конкретное исключение, возможное в базовом классе (почему это отстой-это еще один разговор). Как и в этом случае, любой, кто использует подклассы, сможет поймать это, независимо от того, какое конкретное исключение вы создадите.
Скажем, что это был другой путь вокруг. Базовый класс бросает
ArgumentNullException
и подклассException
. Теперь любой, кто только знает о базовом классе, будет иметь только блоки catch дляArgumentNullException
, поскольку это то, что они ожидают. Их поэтому приложение не будет работать, когда подкласс бросаетException
.class MyClass { public virtual void Foo() { if (true) throw new ArgumentNullException(); } } } class MyDerivedClass : MyClass { public override void Foo() { if (true) throw new Exception(); } } } public class Program { public static void Main() { try { // a factory creating the correct // MyClass derived instance var myClass = someFactory.Create(); myClass.Foo(); } catch (ArgumentNullException) { // won't work since the subclass // violates LSP } } }
В опубликованном коде нет проблем с подтипами, потому что в обоих случаях вы ловите исключение в той же области, в которой оно было вызвано. Но предположим, что производные
foo
не было предложения catch , и базовый класс имел следующий код:try { this.foo(); } catch (ArgumentOutOfRangeException e) { ... }
Базовый класс делает предположение, что
foo
только бросает ArgumentOutOfRange, который производный класс нарушил бы, бросив ArgumentNull.
Более полное понимание принципа замещения Лискова можно найти здесь
https://stackoverflow.com/search?q=liskov + замещение + Принцип