标签: liskov-substitution-principle

复合模式是SOLID吗?

叶在综合模式实现了Component接口,包括Add,Remove,和GetChild方法,一个叶是永远不会使用.这似乎违反了接口隔离原则.

那么复合模式SOLID的用法是什么?

链接到Composite Pattern:http://www.dofactory.com/Patterns/PatternComposite.aspx

design-patterns liskov-substitution-principle composite solid-principles interface-segregation-principle

11
推荐指数
2
解决办法
2389
查看次数

如何遵守Liskov的替换原则(LSP)并仍然受益于多态性?

LSP说"派生类型不能改变基类型的行为",换言之,"派生类型必须完全可替换它们的基类型".

这意味着如果我们在基类中定义虚方法,我们就违反了这个原则.

此外,如果我们使用new关键字在驱动方法中隐藏方法,那么我们又违反了这个原则.

换句话说,如果我们使用多态,我们就违反了LSP!

在许多应用程序中,我在基类中使用了虚方法,现在我意识到它违反了LSP.此外,如果你使用模板方法模式,你违反了这个原则,我已经使用了很多.

那么,当你需要继承并且你也想从多态中受益时,如何设计符合这个原则的应用程序呢?我糊涂了!

请参阅此处的示例:http://www.oodesign.com/liskov-s-substitution-principle.html

c# polymorphism liskov-substitution-principle solid-principles

11
推荐指数
2
解决办法
4851
查看次数

什么是拒绝遗赠?

有人可以解释一下Refused Bequest的含义吗?我尝试阅读一些文章,并说它是一种代码气味,或者在wiki中它告诉它它是一个类,它覆盖基类的方法,使得基类的契约不受派生类的尊重.

但简而言之,或者更简单的说法,实际上是什么?

duck-typing liskov-substitution-principle solid-principles

11
推荐指数
1
解决办法
3904
查看次数

重写getPreferredSize()会破坏LSP

我总是在这个覆盖的站点中看到建议,getPreferredSize() 而不是setPreferredSize() 像以前的这些线程中所示那样使用.

  1. 使用重写getPreferredSize()而不是对固定大小的组件使用setPreferredSize()
  2. 我应该避免在Java Swing中使用set(Preferred | Maximum | Minimum)Size方法吗?
  3. 重写setPreferredSize()和getPreferredSize()

看这个例子:

public class MyPanel extends JPanel{

  private final Dimension dim = new Dimension(500,500); 

  @Override
  public Dimension getPreferredSize(){
      return new Dimension(dim);
  }

 public static void main(String args[]){
      JComponent component = new MyPanel();
      component.setPreferredSize(new Dimension(400,400));
      System.out.println(component.getPreferredSize());
 }

}
Run Code Online (Sandbox Code Playgroud)

setPreferredSize()

  • 设置此组件的首选大小.

getPreferredSize()

  • 如果preferredSize已设置为非null值,则返回它.如果UI委托的getPreferredSize方法返回非null值,则返回该值; 否则遵从组件的布局管理器.

所以这样做显然打破了Liskov替代原则.

prefferedSize是一个绑定属性,所以当你设置它时firePropertyChange执行.所以我的问题是,当你覆盖时,getPrefferedSize()你不需要覆盖setPreferredSize(..)吗?

例:

 public class MyPanel extends JPanel{

  private Dimension dim = null; 

  @Override
  public Dimension …
Run Code Online (Sandbox Code Playgroud)

java swing liskov-substitution-principle jcomponent

10
推荐指数
2
解决办法
924
查看次数

C#接口实现关系只是"可以做"的关系?

今天有人告诉我,C#中的接口实现只是"Can-Do"关系,而不是"Is-A"关系.这与我长期相信LSP(Liskov Substitution Principle)相冲突.我一直认为所有的继承都应该意味着"Is-A"的关系.

所以,如果接口实现只是一个"可以做"的关系.如果有一个界面"IHuman"和"IEngineer",并且一个类"Programmer"继承自"IHuman"和"IEngineer"怎么办?当然,"程序员"是"IHuman"和"IEngineer".

如果只是"Can-Do"关系,是否意味着我们不能指望"程序员"实例行为在被视为IHuman并被视为IEngineer时可能会有所不同?

c# inheritance liskov-substitution-principle interface

9
推荐指数
2
解决办法
7691
查看次数

Liskov替代和组成

假设我有这样一个类:

public sealed class Foo
{
    public void Bar
    {
       // Do Bar Stuff
    }
}
Run Code Online (Sandbox Code Playgroud)

我想扩展它以添加超出扩展方法可以做的事情....我唯一的选择是组合:

public class SuperFoo
{
    private Foo _internalFoo;

    public SuperFoo()
    {
        _internalFoo = new Foo();        
    }

    public void Bar()
    {
        _internalFoo.Bar();
    }

    public void Baz()
    {
        // Do Baz Stuff
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然这有效,但它还有很多工作......但是我仍遇到一个问题:

  public void AcceptsAFoo(Foo a)
Run Code Online (Sandbox Code Playgroud)

我可以在这里传递一个Foo,但不是超级Foo,因为C#不知道SuperFoo确实符合Liskov替换意义......这意味着我的扩展类通过组合使用非常有限.

因此,解决它的唯一方法是希望原始的API设计者留下一个界面:

public interface IFoo
{
     public Bar();
}

public sealed class Foo : IFoo
{
     // etc
}
Run Code Online (Sandbox Code Playgroud)

现在,我可以在SuperFoo上实现IFoo(因为SuperFoo已经实现了Foo,只需要更改签名).

public class SuperFoo : IFoo
Run Code Online (Sandbox Code Playgroud)

在完美的世界中,消耗Foo的方法将消耗IFoo:

public …
Run Code Online (Sandbox Code Playgroud)

.net c# liskov-substitution-principle composition

9
推荐指数
2
解决办法
1416
查看次数

适配器模式与Liskov替换

适配器设计模式用于将类(Target)的接口转换为客户期望的另一个接口(Adaptee).适配器允许不兼容的类一起工作,否则由于它们的不兼容接口而无法工作.

适配器模式可以通过两种方式实现:继承(适配器模式的类版本)和组合(适配器模式的对象版本).

我的问题是关于使用继承实现的适配器模式的类版本.

以下是绘图编辑器的示例:

图1:

interface Shape   
{   
        Rectangle BoundingBox();   

        Manipulator CreateManipulator();   
}   

class TextView   
{   
        public TextView() { }   

        public Point GetOrigin() { }   

        public int GetWidth() { }   

        public int GetHeight() { }   
}  
interface Shape
{
        Rectangle BoundingBox();

        Manipulator CreateManipulator();
}

class TextView
{
        public TextView() { }

        public Point GetOrigin() { }

        public int GetWidth() { }

        public int GetHeight() { }
}
Run Code Online (Sandbox Code Playgroud)

我们想重用TextView类来实现TextShape,但是接口是不同的,因此,TextView和Shape对象不能互换使用.

是否应该更改TextView类以符合形状界面?也许不是.

TextShape可以通过以下两种方式之一使TextView接口适应形状的界面:

  1. 通过继承Shape的接口和TextView的实现(适配器模式的类版本)
  2. 通过在TextShape对象中编写TextView实例并使用TextView实例(适配器模式的对象版本)实现TextShape的接口.

类适配器

图2:

interface Shape   
{   
    Rectangle BoundingBox();   

    Manipulator …
Run Code Online (Sandbox Code Playgroud)

design-patterns liskov-substitution-principle adapter solid-principles

9
推荐指数
1
解决办法
2153
查看次数

不能削弱先决条件和加强后置条件也违反Liskov替代原则吗?

子类型的实际前提是通过(使用逻辑组合创建的OR)的基类型的先决条件亚型的先决条件,这使得所得的先决条件 的限制较少

子类型的实际后置条件是通过(使用逻辑组合创建的AND)碱型的后置一个亚型的后置条件,这使得所得的后置条件 更严格的

以下是加强前提条件弱化后置条件的例子,因此违反了LSP(Link):

  1. 假设您的基类使用成员int.现在你的子类型要求int为正数.这是强化前置条件,现在任何在使用负数之前完全正常工作的代码都会被破坏.

  2. 同样,假设相同的场景,但基类用于保证成员在被调用后是正面的.然后子类型更改行为以允许负的int.由于不支持后置条件,因此对该对象起作用的代码(并假设后置条件为正int)现在已被破坏.

a)当重写方法削弱前提条件时,为什么它也不被视为违反LSP ,因为此方法可以使用基类型合约不可接受的参数.因此,我们不能声称违反了基本类型的合同,因此LSP也被违反了吗?

乙)为什么是不是也认为是违反LSP时覆盖的方法加强后置条件,因为客户端调用此方法将只接收的原始方法的可能结果的一个子集.因此,我们不能声称违反了基本类型的合同,因此LSP也被违反了吗?

例:

基类后置条件保证方法的返回值在范围内1-10,但子类型后置条件更改为仅允许返回值在范围内2-9.现在,由于不支持后置条件,因此破坏了从此方法返回的对象的代码(并假设后置条件在一个范围内1-10).

inheritance liskov-substitution-principle preconditions post-conditions

9
推荐指数
1
解决办法
2195
查看次数

Liskov替换原理和Streams

是否存在无法编写或寻求的Stream派生类的事实是否打破了Liskov替换原则?

例如,无法搜索NetworkStream,NotSupportedException如果Seek调用该方法,它将抛出一个.

或者因为CanSeek旗帜的存在可以吗?

鉴于众所周知的例子Square继承Rectangle......会标志的加入DoesHeightAffectsWidth,并DoesWidthAffectsHeightRectangle解决这个问题?

这不是通过添加标志来打开固定东西的大门吗?

c# oop liskov-substitution-principle stream solid-principles

9
推荐指数
2
解决办法
635
查看次数

避免违反LSP

我想将数据与数据源分开.一个用于数据库交互的类和用于数据操作的类.但是我的方法违反了LSP:preconditions cannot be strengthened in a subtype 并引发了严格的错误:Declaration of DataRepositoryItem::save() should be compatible with DataRepositoryAbstract::save(DataAbstract $data)

class DataAbstract {
}

class DataItem extends DataAbstract {
}

class DataObject extends DataAbstract {
}

abstract class DataRepositoryAbstract {
    /** @return DataAbstract */
    public function loadOne(){}
    /** @return DataAbstract[] */
    public function loadAll(){}                          
    public function save(DataAbstract $data){}
}

class DataRepositoryItem extends DataRepositoryAbstract {
    /** @return DataItem */
    public function loadOne(){}
    /** @return DataItem[] */
    public function loadAll(){}
    public function …
Run Code Online (Sandbox Code Playgroud)

php oop inheritance liskov-substitution-principle solid-principles

9
推荐指数
2
解决办法
384
查看次数