标签: liskov-substitution-principle

继承和LSP

为一个冗长的问题提前道歉.反馈在这里特别赞赏...

在我的工作中,我们做了很多与日期范围的事情(日期时间,如果你愿意).我们需要进行各种测量,比较两个日期之间的重叠等.我设计了一个接口,一个基类和几个派生类,它们满足了我迄今为止的需求:

  • IDatePeriod
  • DatePeriod
  • CalendarMonth
  • CalendarWeek
  • 财政年度

除了它的基本要素之外,DatePeriod超类如下(省略了所有迷人的特性,这些特征是我们为什么需要这组类的基础......):

(Java伪代码):

class datePeriod implements IDatePeriod

protected Calendar periodStartDate
protected Calendar periodEndDate

    public DatePeriod(Calendar startDate, Calendar endDate) throws DatePeriodPrecedenceException
    {
        periodStartDate = startDate
        . . . 
        // Code to ensure that the endDate cannot be set to a date which 
        // precedes the start date (throws exception)
        . . . 
        periodEndDate = endDate
    {

    public void setStartDate(Calendar startDate)
    {
        periodStartDate = startDate
        . . . 
        // Code to ensure that the …
Run Code Online (Sandbox Code Playgroud)

java oop inheritance liskov-substitution-principle

5
推荐指数
1
解决办法
496
查看次数

代码是否符合Liskov的替代原则?

我在升级之前在PHP5.4上测试我现有的代码.我发现以下代码不再有效,因为PHP已经收紧了它的继承模型.由于这种紧缩,我一直在阅读有关SOLID,特别是Liskov的替代原则(我是一名自学成才的程序员),这样我就可以改进我的代码,而不会受到未来"拧紧"的影响.

interface IComparable {
    public function equals(self $other);
}

class A implements IComparable{
    protected $var;

    public function __construct($v){
        $this->var=$v;
    }

    public function equals(self $other){
        return ($this->var == $other->var) ? 'equal' : 'different';
    }
}

$a1= new A(7);
$a2= new A(5);
$a3= new A(5);

echo $a1->equals($a2),"\n";
echo $a2->equals($a3),"\n";
Run Code Online (Sandbox Code Playgroud)

php 5.3结果:

  • 不同
  • 等于

php 5.4结果:

PHP致命错误:A :: equals()的声明必须与IComparable :: equals兼容(IComparable $ other)

如果我以这种方式编写代码,我可以避免php5.4错误:

interface IComparable {
    public function equals($other);
}

class A implements IComparable{
    protected $var;

    public function …
Run Code Online (Sandbox Code Playgroud)

php liskov-substitution-principle

5
推荐指数
1
解决办法
557
查看次数

超载是否违反《里斯科夫替代原则》?

我是OOP的新手。最近,我读到了《里斯科夫替代原理》。

在下面给出的代码中,Square类继承了Give_Area。假设Square类与平方有关(例如有效性检查)。Give_Area给出正方形的面积(4个顶点在一个圆的周长上)和一个圆的面积。因此,如果给我一个Radius,我必须打印圆和正方形的区域(由放置在该圆的周长上的顶点组成)。为了得到一个圆的面积,我使用了一个参数。但是获取平方面积时没有参数。因此,我在这里做了重载。

#include<iostream>
#include<cmath>
using namespace std;

class Give_Area
{
    public:
    double Radius;

    double Area(double pi)
    {
        return pi*Radius*Radius;
    }

    double Area()
    {
        double temp = sqrt(2.0)*Radius;
        return temp*temp;
    }
};

class Square : public Give_Area
{
    public:
    bool Validity()
    {
        //checking validity
    }
};

int main()
{
    Give_Area* area = new Square();
    area->Radius = 3.0;
    cout<< "Area of Circle: " << area->Area(3.14159) <<endl;
    cout<< "Area of Square: " << …
Run Code Online (Sandbox Code Playgroud)

c++ liskov-substitution-principle solid-principles

5
推荐指数
1
解决办法
648
查看次数

为什么在Scala中用`def`覆盖`var`是不可能的?

虽然我理解为什么a var不能覆盖valin子类,反之亦然,但我无法理解为什么Scala不允许defin子类覆盖var超类中的

class Car {
  var age = 32
}

class SedanCar extends Car {
  override def age = 54
}
Run Code Online (Sandbox Code Playgroud)

因为var可变,为什么不允许a def覆盖呢?有人可以帮我理解这个吗?

scala liskov-substitution-principle immutability mutability uap

5
推荐指数
1
解决办法
805
查看次数

接口继承:你怎么看待这个:

在查看我们的代码库时,我发现了一个类似于以下模式的继承结构:

interface IBase
{
    void Method1();
    void Method2();
}

interface IInterface2 : IBase
{
    void Method3();
}

class Class1 : IInterface2
{
    ...
}

class Class2 : IInterface2
{
    ...
}

class Class3 : IInterface2
{ 
    ...
}
Run Code Online (Sandbox Code Playgroud)

Class2,Method1投掷NotImplementedException.

问题:

  • 您对继承接口有何看法?
  • 请问之间的关系IBase,并Class2违反了里氏替换原则?

c# oop inheritance liskov-substitution-principle

4
推荐指数
1
解决办法
6801
查看次数

这是否违反Liskov替代原则,如果是这样,我该怎么办呢?

使用案例:我正在使用数据模板将View与ViewModel相匹配.数据模板通过检查最派生类型提供的具体类型的工作,他们不看什么接口提供,所以我必须这样做没有接口.

我在这里简化了示例并省略了NotifyPropertyChanged等,但在现实世界中,View将绑定到Text属性.为简单起见,假设带有TextBlock的View将绑定到ReadOnlyText,带有TextBox的View将绑定到WritableText.

class ReadOnlyText
{
    private string text = string.Empty;

    public string Text
    {
        get { return text; }
        set
        {
            OnTextSet(value);
        }
    }

    protected virtual void OnTextSet(string value)
    {
        throw new InvalidOperationException("Text is readonly.");
    }

    protected void SetText(string value)
    {
        text = value;
        // in reality we'd NotifyPropertyChanged in here
    }
}

class WritableText : ReadOnlyText
{
    protected override void OnTextSet(string value)
    {
        // call out to business logic here, validation, etc.
        SetText(value);
    }
}
Run Code Online (Sandbox Code Playgroud)

通过重写OnTextSet并改变其行为,我是否违反了LSP?如果是这样,有什么更好的方法呢?

c# wpf liskov-substitution-principle mvvm

4
推荐指数
2
解决办法
769
查看次数

liskov 替换原则违反

我在学习liskov substitution principle。它说sub classes should be proper replacement for the base classes

我读了一个例子,我在互联网的不同地方找到了这个例子。一类Rectangle.javaheight, width他们setter and getter methods。一个Square.java只需要一个属性的类,即length. 如果我们有,Square.java extending Rectangle.java那么这违反了这一原则。这是因为Rectangle.java期望的用户width只要height修改就不会受到影响,反之亦然。

我的疑惑:

  1. 我们看到的情况是,方法只是用空的打开和关闭大括号覆盖,以防止执行在基类中编写的默认代码。这种情况是否违反了这一原则?

  2. 这个原则也说不inheritance应该仅仅用于重用代码。在下面的情况下,这是一种不好的做法,这是否违反了这一原则?

如果类 Window.java 可从某个图形库获得。假设它具有绘制窗口所需的所有代码。还假设它在使用和绘制时有一个工具栏。如果要求是创建一个没有工具栏的窗口。

简单地创建一个 WindowWithoutToolBar.java 扩展 Window.java 并覆盖 drawToolBarMethod() 并将其留空就可以解决目的。 [可能只是创建工具栏而不是绘制它,以避免其他方法尝试访问工具栏时发生任何异常object] 这是一种不好的做法吗?

创建一个没有工具栏的全新 Window 类将需要重写所有已经在 Window.java 中编写的代码。

  1. 对于数字,如果我们有一个 Integer.java 类,其中包含用于各种算术运算的代码,这些算术运算可以使用整数进行平方等。如果我们以后需要 NaturalNumber.java,我们可以轻松地从现有的 Integer 扩展它。 java 并添加检查以仅将正整数作为输入。

现在如果我们需要 AbsoluteNumber.java 那么如果我们从 Integer.java 扩展它,这是否违反了这个原则(如果 Integer.java 有一些方法如 getValueAfterMultiplyByNegativeOne())? …

oop liskov-substitution-principle solid-principles

4
推荐指数
1
解决办法
2393
查看次数

是否有可能在构造函数中违反Liskov替换原则?

我刚刚安装了Microsoft Code Contracts.它是.NET Framework和Visual Studio插件的一部分.它提供运行时检查和定义合同的静态检查.

该工具有四个警告级别,所以我设置最高.

我已经宣布了违反Liskov替代原则的课程.

public class Person
{
    protected int Age { get; set; }

    public Person(int age)
    {
        Contract.Requires(age > 0);
        Contract.Requires(age < 130);
        this.Age = age;
    }
}

public class Child : Person
{
    public Child(int age) : base(age)
    {
        Contract.Requires(age > 0); 
        Contract.Requires(age < Consts.AgeOfMajority);
        Contract.Requires(age < 130);
        this.Age = age;
    }
}

public static class Consts
{
    public readonly static int AgeOfMajority = 18;
}
Run Code Online (Sandbox Code Playgroud)

LSP声明:

如果S是T的子类型,那么类型T的对象可以用类型S的对象替换而不改变该程序的任何所需属性

在我的例子中,违规将是这个对齐:Person person = new Child(23); …

c# liskov-substitution-principle code-contracts solid-principles

4
推荐指数
2
解决办法
562
查看次数

Array.Add方法是否违反了LSP?

Arrayclass实现IList具有Add成员的接口.Array.Add调用抛出NotSupportedException.这是违反Liskov替代原则还是接口隔离原则或两者兼而有之?

.net c# oop liskov-substitution-principle solid-principles

4
推荐指数
1
解决办法
252
查看次数

Mypy 在 __init__ 覆盖中接受不兼容的类型

我有以下Foo基类,并且Bar继承自它:

class Foo:
    def __init__(self, x: int) -> None:
        self._x = x

    def do(self, x: int) -> None:
        pass


class Bar(Foo):
    pass
Run Code Online (Sandbox Code Playgroud)

如果我重写Foo.doin Bar,并将参数的类型更改x为不兼容的内容(即不比 更通用int),那么 Mypy 将返回错误 - 这当然是我所期望的。

class Bar(Foo):
    def do(self, x: str) -> None:
        pass
Run Code Online (Sandbox Code Playgroud)

错误:

test.py:10: error: Argument 1 of "do" is incompatible with supertype "Foo"; supertype defines the argument type as "int"
test.py:10: note: This violates the Liskov substitution principle
test.py:10: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides …
Run Code Online (Sandbox Code Playgroud)

python types liskov-substitution-principle mypy python-typing

4
推荐指数
1
解决办法
1111
查看次数