-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathLSP.cpp
More file actions
133 lines (108 loc) · 3.31 KB
/
LSP.cpp
File metadata and controls
133 lines (108 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// ===========================================================================
// LSP.cpp // Liskov's Substitution Principle
// ===========================================================================
#include <iostream>
#include <string>
#include <cassert>
namespace LiskovSubstitutionPrinciple01
{
struct Rectangle
{
protected:
size_t m_width;
size_t m_height;
public:
Rectangle(size_t width, size_t height)
: m_width{ width }, m_height{ height } {}
// getter / setter
size_t getWidth() const { return m_width; }
size_t getHeight() const { return m_height; }
virtual void setWidth(size_t width) { m_width = width; }
virtual void setHeight(size_t height) { m_height = height; }
// public interface
size_t area() const { return m_width * m_height; }
};
struct Square : public Rectangle
{
Square(size_t size) : Rectangle{ size, size } {}
// getter / setter
void setWidth(size_t width) override {
m_width = m_height = width;
}
void setHeight(size_t height) override {
m_height = m_width = height;
}
};
static void process(Rectangle& r) {
size_t w{ r.getWidth() };
r.setHeight(10);
//assert((w * 10) == r.area()); // fails for Square <-- !!!
}
static void process2(Rectangle& r) {
size_t w{ r.getWidth() };
r.setHeight(10);
if (dynamic_cast<Square*>(&r) != nullptr)
assert((r.getWidth() * r.getWidth()) == r.area());
else
assert((w * 10) == r.area());
}
}
namespace LiskovSubstitutionPrinciple02
{
struct IShape
{
virtual size_t area() const = 0;
};
struct Rectangle : public IShape
{
private:
size_t m_width;
size_t m_height;
public:
Rectangle(size_t width, size_t height)
: m_width{ width }, m_height{ height } {}
// getter / setter
size_t getWidth() const { return m_width; }
size_t getWeight() const { return m_height; }
virtual void setWidth(size_t width) { m_width = width; }
virtual void setHeight(size_t height) { m_height = height; }
// public interface
size_t area() const override { return m_width * m_height; }
};
struct Square : public IShape
{
private:
size_t m_size;
public:
Square(size_t size) : m_size{ size } {}
// getter / setter
size_t getSize() const { return m_size; }
void setSize(size_t size) { m_size = size; }
// public interface
size_t area() const override { return m_size * m_size; }
};
static void process(IShape& s)
{
// use polymorphic behaviour only, e.g. area()
}
}
static void test_anti_conceptual_example_lsp()
{
using namespace LiskovSubstitutionPrinciple01;
Rectangle r{ 5, 5 };
process(r);
Square s{ 5 };
process(s);
}
static void test_conceptual_example_lsp()
{
using namespace LiskovSubstitutionPrinciple02;
}
void test_lsp()
{
test_anti_conceptual_example_lsp();
test_conceptual_example_lsp();
}
// ===========================================================================
// End-of-File
// ===========================================================================