如果我有类似的东西
class square : figure {}
class triangle : figure {}
Run Code Online (Sandbox Code Playgroud)
这是否意味着我永远不应该使用方形和三角形类,而只是参考图?
就像从来没有这样:
var x = new square();
Run Code Online (Sandbox Code Playgroud) 我尝试创建一个继承System.ICloneable接口的通用接口,但Clone()方法的返回类型为T.当然,T类型需要约束以确保它是System.Object类的继承但是以下代码无效.
public interface ICloneable<T> : System.ICloneable where T : object {
T Clone ();
}
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
此外,以下约束不起作用:
在这种情况下,我如何使用Liskov原则,说明您可以缩小返回类型,以解决此问题?
PS:对不起我的英语,如果我犯了错误.我不是母语为英语的人.
我正在尝试以正确的方式学习OOP和OOD原则.我想对Liskov替换原则及其PRE和POST条件做一些澄清.我在这里阅读了一些主题,一些文章来自http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod等地方.
我已经编写了一个简单的基类和几个示例子类,我的假设是关于它们的前后条件,我想知道它们是否正确.注释行是我的想法:是否违反了PRE和POST条件.
public abstract class BaseClass
{
public virtual int GetResult(int x, int y)
{
if (x > 10 && y < 20)
{
return y - x;
}
throw new Exception();
}
}
public class LSPExample1 : BaseClass
{
public override int GetResult(int x, int y)
{
// PRE: weakened pre condition is ok
if (x > 10 && y <= 15)
{
// POST: Is it ok? because the available result range is narrowed by y …Run Code Online (Sandbox Code Playgroud) 这是在接受采访时向我询问的.
我回答他说,对于同一组输入,父母和孩子都应该产生相同的输出.如果孩子想要扩展父母的功能,它应该只对父母支持范围之外的新输入做.通过这种方式,孩子将保持其父母的合同.
我给了他一个例子,api可能正在使用像这样的父母
if(parent.getOutput(10) == 5){/*do something */}
Run Code Online (Sandbox Code Playgroud)
如果孩子在这里产生了不同的输出,那么那个孩子已经违反了它的父母所做的合同.
他对我的回答并不满意,并告诉我这是简单的重写,并不违反LSP.所以,我只是想确认,如果我理解这是正确的.
里氏替换原则指出:
程序中的对象应该可以用其子类型的实例替换,而不改变该程序的正确性。
假如说:
interface Iterable<T> {
fun getIterator(): Iterator<T>
}
interface Collection<T> : Iterable<T> {
val size: Int
}
interface List<T> : Collection<T> {
fun get(index: Int): T
}
interface MutableList<T> : List<T> {
fun set(index: Int, item: T): Unit
}
Run Code Online (Sandbox Code Playgroud)
当 LSP 应用于输入参数时,应应用最低级别的抽象:
做
fun foo(items: Iterable<Any>) { ... }
Run Code Online (Sandbox Code Playgroud)
不
fun foo(items: List<Any>) { ... }
Run Code Online (Sandbox Code Playgroud)
但是,LSP 是否适用于函数返回类型?如果适用,则反之亦然吗?
fun bar(): Iterable<Any> { ... }
Run Code Online (Sandbox Code Playgroud)
或者
fun bar(): List<Any> { ... }
Run Code Online (Sandbox Code Playgroud) 每个类直接或间接地从Object类继承.
Object除了其他人之外,这个班级有一个重要的方法,最经常被覆盖:toString.
问题是:这个方法的重写不会导致Liskov替换原则违反了Object类吗?
我会做一个例子.
public class Main
{
public static void main(String[] args)
{
Object o = new Object();
String s = o.toString();
if (s.indexOf('@') > -1) {
System.out.println("OK");
} else {
System.out.println(":-(");
}
}
}
public class MyClass
{
private int x;
public string toString()
{
return Integer.toString(x);
}
}
Run Code Online (Sandbox Code Playgroud)
显然,如果我更换new Object()与new MyClass()系统的行为变化.
我想避免使用将基类类型转换为派生类类型的方法,我可以成功完成此操作。
我已经编写了代码来演示我已经尝试过的内容。
public abstract class Animal : IAnimal
{
public void Move()
{
}
}
public interface IAnimal
{
void Move();
}
public interface IDog:IAnimal
{
void bark();
}
public class Dog : IDog
{
public void Move()
{
}
public void bark()
{
}
}
static void Main(string[] args)
{
Animal animal = null;
IDog dog = animal as IDog;
dog.bark(); // can access specialized method
IAnimal puppy = new Dog();
puppy.Move(); // can only access generic functions
} …Run Code Online (Sandbox Code Playgroud)