Professional Documents
Culture Documents
inheritance
Problems
Identify the appropriate example(s) or section(s) of the chapter to illustrate each comment
made in the summary at the end of chapter 7.
Reconsider the ‘deep hierarchy’ version of problem 3.3. In what ways does this violate the
requirements for implementation inheritance, and which of the anti-patterns listed in this
chapter does it contravene?
To answer this question, maybe a good start is to go back to the basic test for
implementation inheritance, which chapter 7 p13 gives as: ‘The basic test for
implementation inheritance is the IsA test. Is the proposed subclass a superclass in all
respects? Do all features of the superclass apply to the subclass, possibly with some
extensions but with minimal need for overriding?’
Applying this to example 3.3, we can ask: ‘Is a TBoxSmall a TBoxLarge, possibly with
some extensions?’ No it is not. And is a TBoxLarge a TItem, possibly with extensions?
Using and abusing inheritance (23 Sep 2006, all rights reserved) Chapter 7, Page 1
Again, no. So the deep hierarchy structure fails the IsA test.
The deep hierarchy falls foul of anti-pattern 7.1. Depending on the implementation
there may be methods in TBoxLarge that do not apply to TBoxSmall, in which case
TBoxSmall exposes methods in TBoxLarge inappropriately. (Some students did not use
the existing data fields in TBoxLarge for TBoxSmall but declared additional data fields: in
this case TBoxSmall is also exposing TBoxLarge’s unused data fields.)
The limiting visibility anti-pattern (7.2) does not apply here since it refers to writing
methods in the subclass specifically to void the matching method in the superclass. This
has not been done here.
One can argue that this also breaks the construction convenience anti-pattern (7.4).
One might also consider the role test, which is the other test for implementation
inheritance. None of these are roles of the other (a small box won’t suddenly become a
large box) and so it is valid to have all of these in the same inheritance hierarchy.
Fortunately, the shallow hierarchy meets all of the criteria above.
Reimplement the ‘shallow hierarchy’ version of problem 3.3, taking advantage of concepts,
such as polymorphism and abstract classes, that have been introduced after chapter 3. The
following framework may be helpful in this reimplementation.
1 unit BoxCountU;
2 interface
3 uses
4 Windows, Messages, SysUtils, Variants, classes, Graphics,
5 Controls, Forms, Dialogs, StdCtrls, Buttons, ExtCtrls,
6 ItemCountU;
7 type
8 TfrmCount = class(TForm)
9 // standard RAD declarations
31 private
32 procedure DisplayValues;
33 procedure UpdateCount (APackage: TItemCount;
34 ADirection: integer);
35 end; // end TfrmCount = class(TForm)
38 implementation
39 uses
40 ItemU, BoxLargeU, BoxSmallU;
41 const
42 Into = 0;
43 OutOf = 1;
44 var
45 ItemCount: TItem;
46 LargeBoxCount: TBoxLarge;
47 SmallBoxCount: TBoxSmall;
48 {$R *.dfm}
70 procedure TfrmCount.DisplayValues;
71 var
72 TotalCount: integer;
73 begin
74 lblItems.Caption := IntToStr(ItemCount.GetCount);
75 lblLargeBoxes.Caption := IntToStr(LargeBoxCount.GetCount);
76 lblSmallBoxes.Caption := IntToStr(SmallBoxCount.GetCount);
77 TotalCount := ItemCount.GetTotal +
78 LargeBoxCount.GetTotal + SmallBoxCount.GetTotal;
79 lblTotal.Caption := IntToStr(TotalCount);
80 end; // end procedure TfrmCount.DisplayValues
Using and abusing inheritance (23 Sep 2006, all rights reserved) Chapter 7, Page 3
81 procedure TfrmCount.bmbResetClick(Sender: TObject);
82 begin
83 ItemCount.ZeroCount;
84 SmallBoxCount.ZeroCount;
85 LargeBoxCount.ZeroCount;
86 DisplayValues;
87 end; // end procedure TfrmCount.bmResetClick
88 initialization
89 ItemCount := TItem.Create;
90 LargeBoxCount := TBoxLarge.Create;
91 SmallBoxCount := TBoxSmall.Create;
1 unit ItemCountU;
2 interface
3 type
4 TItemCount = class(TObject)
5 private
6 FCount: integer;
7 public
8 procedure Add;
9 procedure Subtract;
10 function GetCount: integer;
11 function GetTotal: integer; virtual; abstract;
12 procedure ZeroCount;
13 end; // end TItemCount = class(TObject)
14 implementation
{ TItemCount }
procedure TItemCount.Add;
begin
Inc(FCount);
end; // end procedure TItemCount.Add
procedure TItemCount.Subtract;
begin
Inc(FCount, -1);
end; // end procedure TItemCount.Subtract
procedure TItemCount.ZeroCount;
begin
FCount := 0;
1 unit ItemU;
2 interface
3 uses ItemCountU;
4 type
5 TItem = class(TItemCount)
6 public
7 function GetTotal: integer; override;
8 end; // end TItem = class(TItemCount)
9 implementation
10 { TItem }
1 unit BoxLargeU;
2 interface
3 uses ItemCountU;
4 type
5 TBoxLarge = class(TItemCount)
6 public
7 function GetTotal: integer; override;
8 end; // end TBoxLarge = class(TItemCount)
9 implementation
10 { TBoxLarge }
11 const
12 NoInBox = 12;
Using and abusing inheritance (23 Sep 2006, all rights reserved) Chapter 7, Page 5
13 { Implement the concrete methods(s), if any }
1 unit BoxSmallU;
2 interface
3 uses ItemCountU;
4 type
5 TBoxSmall = class(TItemCount)
6 public
7 function GetTotal: integer; override;
8 end; // end TBoxSmall = class(TItemCount)
9 implementation
10 { TBoxSmall }
11 const
12 NoInBox = 4;
The framework given above effectively guides one to adopt the same approach as given in
the assignment discussion of the deep hierarchy version of problem 3.3. The assignment
discussion of the shallow hierarchy version of problem 3.3 presents another variation of a
well-structured OO approach.