Smell Detail

Refused Bequest

被拒绝的遗赠

Object-Orientation Abusers

A subclass does not use (or rejects) some of the methods or data it inherits from its parent.

Define

Introduction

Refused Bequest occurs when a subclass uses only part of its parent's functionality or overrides inherited methods just to throw exceptions. This signals a flawed inheritance design.

Key Identifiers

  • Subclass overrides methods solely to throw exceptions or disable them
  • Subclass ignores or never calls certain inherited methods
  • Inheritance does not reflect a true "is-a" relationship
  • Violates the Liskov Substitution Principle

Refactoring Suggestions

  1. Redesign the Hierarchy: Create a more accurate abstraction
  2. Prefer Composition: Replace inheritance with delegation/composition
  3. Extract Superclass / Interfaces: Factor shared behavior into a proper parent or interface set
  4. Interface Segregation: Split large interfaces into focused ones

Explanation

Penguins cannot fly—yet a Penguin subclass might inherit a fly() method from Bird. This mismatch indicates a hierarchy problem. Redesign by extracting flying capability into a separate interface/trait rather than forcing all birds to implement it.

Code Example
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
class Bird {
public void fly() {
System.out.println("Flying...");
}
public void eat() {
System.out.println("Eating...");
}
public void makeSound() {
System.out.println("Chirp...");
}
public void layEggs() {
System.out.println("Laying eggs...");
}
public void sleep() {
System.out.println("Sleeping...");
}
public void buildNest() {
System.out.println("Building nest...");
}
}
class Penguin extends Bird {
// Refused bequest: Penguins can't fly
@Override
public void fly() {
throw new UnsupportedOperationException("Penguins can't fly!");
}
@Override
public void makeSound() {
System.out.println("Squawk...");
}
public void swim() {
System.out.println("Swimming...");
}
public void slideOnIce() {
System.out.println("Sliding on ice...");
}
}
class Ostrich extends Bird {
// Ostriches also can't fly
@Override
public void fly() {
throw new UnsupportedOperationException("Ostriches can't fly!");
}
// Also refuse nest building behavior
@Override
public void buildNest() {
throw new UnsupportedOperationException("Ostriches don't build nests like other birds!");
}
@Override
public void makeSound() {
System.out.println("Boom...");
}
public void run() {
System.out.println("Running very fast...");
}
public void kickWithPowerfulLegs() {
System.out.println("Kicking with powerful legs...");
}
}
class Kiwi extends Bird {
// Kiwis can't fly either
@Override
public void fly() {
throw new UnsupportedOperationException("Kiwis can't fly!");
}
// Kiwis are nocturnal, so they have different sleep patterns
@Override
public void sleep() {
System.out.println("Sleeping during the day...");
}
public void huntAtNight() {
System.out.println("Hunting for insects at night...");
}
public void digWithBeak() {
System.out.println("Digging in the ground with long beak...");
}
}
// Another example with different inheritance issues
class Vehicle {
public void startEngine() {
System.out.println("Starting engine...");
}
public void drive() {
System.out.println("Driving...");
}
public void refuel() {
System.out.println("Refueling...");
}
public void honk() {
System.out.println("Honking horn...");
}
public void useWipers() {
System.out.println("Using windshield wipers...");
}
}
class Bicycle extends Vehicle {
// Bicycles refuse most vehicle behaviors
@Override
public void startEngine() {
throw new UnsupportedOperationException("Bicycles don't have engines!");
}
@Override
public void refuel() {
throw new UnsupportedOperationException("Bicycles don't need fuel!");
}
@Override
public void honk() {
System.out.println("Ringing bell...");
}
@Override
public void useWipers() {
throw new UnsupportedOperationException("Bicycles don't have windshield wipers!");
}
public void pedal() {
System.out.println("Pedaling...");
}
public void ringBell() {
System.out.println("Ring ring!");
}
}
class ElectricCar extends Vehicle {
// Electric cars refuse some traditional vehicle behaviors
@Override
public void refuel() {
throw new UnsupportedOperationException("Electric cars don't use gasoline!");
}
public void charge() {
System.out.println("Charging battery...");
}
public void enableAutopilot() {
System.out.println("Enabling autopilot...");
}
}
// Demonstration of the problem
class TransportationService {
public void maintainVehicle(Vehicle vehicle) {
try {
vehicle.startEngine();
vehicle.refuel();
vehicle.useWipers();
System.out.println("Vehicle maintenance completed");
} catch (UnsupportedOperationException e) {
System.out.println("Maintenance failed: " + e.getMessage());
}
}
public void trainBird(Bird bird) {
try {
bird.fly();
bird.buildNest();
System.out.println("Bird training completed");
} catch (UnsupportedOperationException e) {
System.out.println("Training failed: " + e.getMessage());
}
}
// This method shows the Liskov Substitution Principle violation
public void demonstrateFlightCapability(Bird[] birds) {
for (Bird bird : birds) {
try {
System.out.println("Testing flight for " + bird.getClass().getSimpleName());
bird.fly(); // Some birds will throw exceptions!
} catch (UnsupportedOperationException e) {
System.out.println("Cannot fly: " + e.getMessage());
}
}
}
public static void demonstrateProblems() {
TransportationService service = new TransportationService();
// Bird hierarchy problems
Bird[] birds = {
new Penguin(),
new Ostrich(),
new Kiwi()
};
service.demonstrateFlightCapability(birds);
// Vehicle hierarchy problems
Vehicle[] vehicles = {
new Bicycle(),
new ElectricCar()
};
for (Vehicle vehicle : vehicles) {
System.out.println("\nMaintaining " + vehicle.getClass().getSimpleName());
service.maintainVehicle(vehicle);
}
}
}