- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
几天来,我一直在尝试理解 Liskov 替换原则,在使用非常典型的 Rectangle/Square 示例进行一些代码测试时,我创建了下面的代码,并提出了 2 个关于它的问题。
问题 1:如果我们有父类(super class)/子类关系,为什么我们要将一个实例声明为父类(super class)型,但将其实例化(新建)为子类型?
我理解为什么,如果我们通过接口(interface)进行多态性,我们希望以这种方式声明和实例化变量:
IAnimal dog = new Dog();
Animal dog = new Dog();
Square sq = new Square();
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var rect = new Rectangle(300, 150);
var sq = new Square(100);
Rectangle liskov = new Square(50);
var list = new List<Rectangle> {rect, sq, liskov};
foreach(Rectangle r in list)
{
r.SetWidth(90);
r.SetHeight(80);
r.PrintSize();
r.PrintMyType();
Console.WriteLine("-----");
}
Console.ReadLine();
}
public class Rectangle
{
protected int _width;
protected int _height;
public Rectangle(int width, int height)
{
_width = width;
_height = height;
}
public void PrintMyType()
{
Console.WriteLine(this.GetType());
}
public void PrintSize()
{
Console.WriteLine(string.Format("Width: {0}, Height: {1}", _width, _height));
}
public virtual void SetWidth(int value)
{
_width = value;
}
public virtual void SetHeight(int value)
{
_height = value;
}
public int Width { get { return _width; } }
public int Height { get { return _height; } }
}
public class Square : Rectangle
{
public Square(int size) : base(size, size) {}
public override void SetWidth(int value)
{
base.SetWidth(value);
base.SetHeight(value);
}
public override void SetHeight(int value)
{
base.SetHeight(value);
base.SetWidth(value);
}
}
}
最佳答案
Question 1: If we have a superclass/subclass relationship, why would we want to declare an instance as the supertype but instantiate it (new it up) as the subtype?
abstract class Car { ... }
public abstract class ToyotaCamery2011 extends Car ( ... )
class Garage {
private Car car = new ToyotaCamery2011();
public Car getCar() { return car; }
....
}
class Garage {
private ToyotaCamery2011 toyotaCamery2011 = new ToyotaCamery2011();
public Car getCar() { return toyotaCamery2011; }
....
}
Garage
的所有方法只使用
Car
的方法,以及
Garage
的公共(public)接口(interface)只显示
Car
并没有特定于
Prius2011
,这两个类实际上是等价的。哪个更容易理解,例如哪一个更接近现实世界?这可以确保我不会意外使用 Prius 专用方法,即 build 一个 Prius 专用车库?如果我决定买一辆新车,哪一个更容易维护?代码是否使用特定子类型以任何方式改进?
Question 2: So, why or how would this code sample be breaking the LSP? Is it only because of the Square invariant of all sides being equal breaks the Rectangle invariant that sides can be modified independently? If that's the reason, then the LSP violation would be theoretical only? Or how, in code, could I see this code breaking the principle?
Rectangle
promise 边可以独立修改(更正式地说,如果调用
Rectangle.setWidth()
的后置条件包括 Rectangle.getHeight() 应该不受影响),那么
Square
源自
Rectangle
打破 LSP。
Rectangle
的想法。有独立的边。
Rectangle
的类作为输入并取决于
Rectangle
的此属性/行为给定
Square
时可能会中断作为输入。像这样的程序可以跳过箍来寻找和禁止
Square
(这是一个子类的知识)或者它可以改变
Rectangle
的契约(Contract)关于独立尺寸。然后所有使用
Rectangle
的程序可以在每次调用
setWidth()
后查看或 setLength()
to see whether the adjacent side also changed and react accordingly. If it does the latter, than
广场
deriving frmo
Rectangle` 不再违反 LSP。
Iterator
类提供
remove()
可选的方法。使用迭代器的类必须了解实现类和/或其子类,才能知道使用它是否安全
Iterator.remove()
.这违反了 LSP,但它在 Java 中被接受。它使编写和维护软件更复杂,更容易受到错误的影响。
Question 3: The Open-Closed principle states that we should introduce new behavior/functionality through new classes (inheritance or interfaces). So if for example, I have a WriteLog method in the base class, which has no preconditions, but I introduce a new subclass which overrides the method but ONLY actually writes to the log if the event is highly critical....if this is new intended functionality (precondition being hardened on the subtype), would that still be breaking the LSP? The two principles would appear to contradict one another in this case.
关于inheritance - 为什么将实例声明为父类(super class)型却将其实例化为子类型,加上里氏替换原则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4871618/
我正在尝试编写一个相当多态的库。我遇到了一种更容易表现出来却很难说出来的情况。它看起来有点像这样: {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE
谁能解释一下这个表达式是如何工作的? type = type || 'any'; 这是否意味着如果类型未定义则使用“任意”? 最佳答案 如果 type 为“falsy”(即 false,或 undef
我有一个界面,在IAnimal.fs中, namespace Kingdom type IAnimal = abstract member Eat : Food -> unit 以及另一个成功
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: What is the difference between (type)value and type(va
在 C# 中,default(Nullable) 之间有区别吗? (或 default(long?) )和 default(long) ? Long只是一个例子,它可以是任何其他struct类型。 最
假设我有一个案例类: case class Foo(num: Int, str: String, bool: Boolean) 现在我还有一个简单的包装器: sealed trait Wrapper[
这个问题在这里已经有了答案: Create C# delegate type with ref parameter at runtime (1 个回答) 关闭 2 年前。 为了即时创建委托(dele
我正在尝试获取图像的 dct。一开始我遇到了错误 The function/feature is not implemented (Odd-size DCT's are not implemented
我正在尝试使用 AFNetworking 的 AFPropertyListRequestOperation,但是当我尝试下载它时,出现错误 预期的内容类型{( “应用程序/x-plist” )}, 得
我在下面收到错误。我知道这段代码的意思,但我不知道界面应该是什么样子: Element implicitly has an 'any' type because index expression is
我尝试将 SignalType 从 ReactiveCocoa 扩展为自定义 ErrorType,代码如下所示 enum MyError: ErrorType { // .. cases }
我无法在任何其他问题中找到答案。假设我有一个抽象父类(super class) Abstract0,它有两个子类 Concrete1 和 Concrete1。我希望能够在 Abstract0 中定义类
我想知道为什么这个索引没有用在 RANGE 类型中,而是用在 INDEX 中: 索引: CREATE INDEX myindex ON orders(order_date); 查询: EXPLAIN
我正在使用 RxJava,现在我尝试通过提供 lambda 来订阅可观察对象: observableProvider.stringForKey(CURRENT_DELETED_ID) .sub
我已经尝试了几乎所有解决问题的方法,其中包括。为 提供类型使用app.use(express.static('public'))还有更多,但我似乎无法为此找到解决方案。 index.js : imp
以下哪个 CSS 选择器更快? input[type="submit"] { /* styles */ } 或 [type="submit"] { /* styles */ } 只是好
我不知道这个设置有什么问题,我在 IDEA 中获得了所有注释(@Controller、@Repository、@Service),它在行号左侧显示 bean,然后转到该 bean。 这是错误: 14-
我听从了建议 registering java function as a callback in C function并且可以使用“简单”类型(例如整数和字符串)进行回调,例如: jstring j
有一些 java 类,加载到 Oracle 数据库(版本 11g)和 pl/sql 函数包装器: create or replace function getDataFromJava( in_uLis
我已经从 David Walsh 的 css 动画回调中获取代码并将其修改为 TypeScript。但是,我收到一个错误,我不知道为什么: interface IBrowserPrefix { [
我是一名优秀的程序员,十分优秀!