Related
I have a data class which encapsulates relevant data items in it. Those data items are set and get by users one by one when needed.
My confusion about the design has to do with which object should be responsible for handling the update of multiple properties of that data object. Sometimes an update operation will be performed which affects many properties at once.
So, which class should have the update() method?. Is it the data class itself or another manager class ? The update() method requires data exchange with many different objects, so I don't want to make it a member of the data class because I believe it should know nothing about the other objects required for update. I want the data class to be only a data-structure. Am I thinking wrong? What would be the right approach?
My code:
class RefData
{
Matrix mX;
Vector mV;
int mA;
bool mB;
getX();
setB();
update(); // which affects almost any member attributes in the class, but requires many relations with many different classes, which makes this class dependant on them.
}
or,
class RefDataUpdater
{
update(RefData*); // something like this ?
}
There is this really great section in the book Clean Code, by Robert C. Martin, that speaks directly to this issue.
And the answer is it depends. It depends on what you are trying to accomplish in your design--and
if you might have more than one data-object that exhibit similar behaviors.
First, your data class could be considered a Data Transfer Object (DTO). As such, its ideal form is simply a class without any public methods--only public properties -- basically a data structure. It will not encapsulate any behavior, it simply groups together related data. Since other objects manipulate these data objects, if you were to add a property to the data object, you'd need to change all the other objects that have functions that now need to access that new property. However, on the flip side, if you added a new function to a manager class, you need to make zero changes to the data object class.
So, I think often you want to think about how many data objects might have an update function that relates directly to the properties of that class. If you have 5 classes that contain 3-4 properties but all have an update function, then I'd lean toward having the update function be part of the "data-class" (which is more of an OO-design). But, if you have one data-class in which it is likely to have properties added to it in the future, then I'd lean toward the DTO design (object as a data structure)--which is more procedural (requiring other functions to manipulate it) but still can be part of an otherwise Object Oriented architecture.
All this being said, as Robert Martin points out in the book:
There are ways around this that are well known to experienced
object-oriented designers: VISITOR, or dual-dispatch, for example.
But these techniques carry costs of their own and generally return the
structure to that of a procedural program.
Now, in the code you show, you have properties with types of Vector, and Matrix, which are probably more complex types than a simple DTO would contain, so you may want to think about what those represent and whether they could be moved to separate classes--with different functions to manipulate--as you typically would not expose a Matrix or a Vector directly as a property, but encapsulate them.
As already written, it depends, but I'd probably go with an external support class that handles the update.
For once, I'd like to know why you'd use such a method? I believe it's safe to assume that the class doesn't only call setter methods for a list of parameters it receives, but I'll consider this case as well
1) the trivial updater method
In this case I mean something like this:
public update(a, b, c)
{
setA(a);
setB(b);
setC(c);
}
In this case I'd probably not use such a method at all, I'd either define a macro for it or I'd call the setter themselves. But if it must be a method, then I'd place it inside the data class.
2) the complex updater method
The method in this case doesn't only contain calls to setters, but it also contains logic. If the logic is some sort of simple property update logic I'd try to put that logic inside the setters (that's what they are for in the first place), but if the logic involves multiple properties I'd put this logic inside an external supporting class (or a business logic class if any appropriate already there) since it's not a great idea having logic reside inside data classes.
Developing clear code that can be easily understood is very important and it's my belief that by putting logic of any kind (except for say setter logic) inside data classes won't help you achieving that.
Edit
I just though I'd add something else. Where to put such methods also depend upon your class and what purpose it fulfills. If we're talking for instance about Business/Domain Object classes, and we're not using an Anemic Domain Model these classes are allowed (and should contain) behavior/logic.
On the other hand, if this data class is say an Entity (persistence objects) which is not used in the Domain Model as well (complex Domain Model) I would strongly advice against placing logic inside them. The same goes for data classes which "feel" like pure data objects (more like structs), don't pollute them, keep the logic outside.
I guess like everywhere in software, there's no silver bullet and the right answer is: it depends (upon the classes, what this update method is doing, what's the architecture behind the application and other application specific considerations).
I've had trouble finding a clear, concise laymans definition of a class. Usually, they give general ideas without specifically spelling it out, and I'm wondering if I'm understanding this correctly. As I understand it, a class is the set of code that controls an object. For example, in an app that has a button for 'Yes' and a button for 'No', and a text box for output, the code that tells the computer what to do when the user uses the Yes button is one class, the code for hitting No is another class, and an object is the two buttons and what they do together to influence the output box. Am I right, or am I confusing terms here?
Thanks
A class is a kind of thing, an object is an actual thing. So, in the real world, "person" is a class, you and I are objects (or instances) of that class. "Car" is a class, my 1996 beater Volvo station wagon is an object.
Objects all have certain similarities in form and function because of the class they belong to. When I say my station wagon is a "car", you have a pretty good idea of what it looks like, what it's used for, and what it can do. But objects of a class can also differ from each other. Just because something's a car doesn't tell you exactly what shape it is or how many seats it has or what color it is.
In the example you gave, it's likely that the yes and no buttons are both objects of the class "button" (or some similar name) and that the differences in their behavior are due to changes added by the programmer without his or her bothering to create a new class. However, it is possible that the programmer made the decision to make each type of button a subclass of the original class "button".
What's a subclass? Well, if you think of "car" as a class, it is obvious that there are several intermediate "kinds" of things between "car" and "Larry's 1996 beater Volvo station wagon". These could be "station wagon" and "Volvo station wagon". So my car would be an instance of "Volvo station wagon" which itself would be subclass of "station wagon" which would be a subclass of "car". From the "car" part, we know a good deal about my object, from the "station wagon" part we learn a little more, and from the "Volvo station wagon" a little more still.
The way in which classes and subclasses are arranged is a decision made by the programmer. In my example above, another programmer might have made the classes "car", "Volvos", "pre-Ford", and "Wagons". It depends on the problem you're trying to solve.
This is going to be a very simplified explanation. A class is a set of functions and variables and is used to create objects. I think it's good to use real examples instead of dog / bark / talk etc.
Class Email
Subject (string)
Message (string)
ToAddress (string)
FromAddress (string)
Send (function)
When you call 'new Email()' it creates a new object with those variables and functions. Then you can populate the variables and send it.
In object-oriented programming, a class is a type for objects. An object is a bundle of data together with functionality that can operate in the context of that data; the definition of what the object is and does when it is first created is determined by its class.
Like a type for data, the class of an object specifies what is common to all instances of that class. Instances, which are the objects themselves, then get to override that common baseline (otherwise there's not much point having distinct instances). In many OO systems, instances may or may not have new members that are not part of the class definition.
What that means in the context of a specific object-oriented language is going to differ from language to language. But if you think of classes as types, and build on that, you won't go far wrong.
A class is basically a way to organize your code.
It allows you to put all of the code related to one abstraction (think "concept" or "idea") in one place.
As an example - in your example of an app, the Window with the two buttons, a text box, and some code for handling what happens when the user types in the information may be organized into a single class: something like "PromptWindow". This class would be made up of multiple classes internally (two buttons, a textbox, etc) This would probably be used by some separate class, which would create an instance of the PromptWindow class, call a method on the class to show the window, then use the results.
At the very basis, there's procedural code:
var a = 4
var b = 5;
print a + b;
… and so on, statements following statements…
To make such pieces of code reusable, you make a function out of them:
function a_plus_b() {
var a = 4
var b = 5;
print a + b;
}
Now you can use that piece of code as often as you want, but you only had to write it once.
Usually an application depends on a certain way of how pieces of code and variables have to work together. This data needs to be processed by that function, but cannot be processed by that other function.
function foo(data) {
…do something…
return data;
}
function bar(data) {
…do something else…
return data;
}
a = "some data";
b = 123456;
a = foo(a);
b = bar(b);
c = bar(a); // ERROR, WRONG DATA FOR FUNCTION
To help group these related parts together, there are classes.
class A {
var data = 'some data';
function foo() {
…do something…
return data;
}
}
The function foo now has a variable data that is "bundled" with it in the same class. It can operate on that variable without having to worry about that it may be the wrong kind of data. Also there's no way that data can accidentally end up in function bar, which is part of another class.
The only problem is, there's only one variable data here. The function is reusable, but it can only operate on one set of data. To solve this, you create objects (also called instances) from the class:
instance1 = new A();
instance2 = new A();
instance1 and instance2 both behave exactly like class A, they both know how to perform function foo (now called an instance method) and they both hold a variable data (now called an instance variable or attribute), but that variable data can hold different data for both instances.
That's the basics of classes and objects. How your particular "OK", "Cancel" dialog box is implemented is a different story. Both buttons could be linked to different methods of different classes, or just to different methods of the same class, or even to the same method of the same class. Classes are just a way to logically group code and data, how that's going to be used is up to you.
In a language agnostic fasion, I would describe a class as being an object that contains related information.
A person class would have methods like Talk(), Walk(), Eat(); and attributes like Height, Color, Language, etc.
A class is like a blueprint of things that you can instantiate, and also procedures that are related to each other.
If you have a Database class, you might have many methods related to databases that do all sorts of voodoo with a database.
A class is a bunch of code that defines an entity in your application. There may be many such entities, but the behaviour of each is the same, as defined by the class. The class will typically define fields, whose contents are local to the instances (or objects) of that class. It is these fields that provide the objects with state and make them distinguishable from one another.
To use your example, there might be a Button class that defines what a button is in your application. This class would then be instantiated twice to provide two objects: one for the "No" button and another for the "Yes" button. The Button class could have a Text field/property that defines what text it contains – this could be set to "No" and "Yes" on the appropriate Button instances to give them their different appearances.
As for the click behaviour of the buttons, this would typically be implemented via the observer pattern, in which the subject class (Button in this case) maintains a list of separate "observer" objects which it notifies whenever some event occurs (i.e. when the button is clicked).
You should look at some sample code, in your language of choice. Just reading about the concept of classes will not answer many questions.
For example, I could tell you that a class is a "blueprint" for an object. Using this class, you can instantiate multiple such objects, each one of them (potentially) having unique attributes.
But you didn't understand a thing, now, did you? Your example with the buttons is very limited. Classes have nothing to do with user interfaces or actions or whatever. They define a way of programming, just like functions/methods/whatever you want to call them do.
So, to give a concrete example, here's a class that defines a ball, written in Python:
class Ball:
color = ''
def __init__(self, color):
self.color = color
def bounce(self):
print "%s ball bounces" % self.color
blueBall = Ball("blue")
redBall = Ball("red")
blueBall.bounce()
redBall.bounce()
Running this produces the expected output:
blue ball bounces
red ball bounces
However, there is much more to classes than I described here. Once you understand what a class is, you go on to learn about constructors, destructors, inheritance and a lot of other good stuff. Break a leg :)
From the definition of Class at Wikipedia:
In object-oriented programming, a
class is a construct that is used as
a blueprint (or template) to create
objects of that class. This blueprint
describes the state and behavior that
the objects of the class all share. An
object of a given class is called an
instance of the class. The class that
contains (and was used to create) that
instance can be considered as the type
of that object, e.g. an object
instance of the "Fruit" class would be
of the type "Fruit".
A class usually represents a noun,
such as a person, place or (possibly
quite abstract) thing - it is a model
of a concept within a computer
program. Fundamentally, it
encapsulates the state and behavior of
the concept it represents. It
encapsulates state through data
placeholders called attributes (or
member variables or instance
variables); it encapsulates behavior
through reusable sections of code
called methods.
Your understanding of a Class isn't at all incorrect but to make things clear consider the following...
The Yes and No buttons plus the TextBox are usually specified within a class taking for example code written in C# (Microsoft .NET Framework). Let's name this class MyClass.
The actions the buttons cause are handled by what are called handlers (methods). You could write your code in such a way that when you click the Yes button something gets written in the TextBox.
To instantiate MyClass you'd do the following:
MyClass myClass = new MyClass();
myClass.ButtonYes += new EventHandler(YourMethodForYes);
myClass.ButtonNo += new EventHandler(YourMethodForNo);
myClass.TextBox.Text = "Yes button was clicked";
Hope you get the idea.
I wrote usually above because this cenario you described could be implemented in a number of ways. OOP gives you plenty of ways to accomplish the same task.
Besides the definition of Class I think that reading about Object Oriented Programming (OOP) can help you a lot to understand it even more. Take a look at Fundamental Concepts.
I have a large Shape class, instances of which can (should) be able to do lots of things. I have many "domain" shape classes which inherit from this class, but do not provide any different functionality other than drawing themselves.
I have tried subclassing the Shape class, but then all of the "domain" objects will still inherit this subclass.
How do I break up the class? (it is 300 text lines, C#)
300 lines seems reasonable to me.
post the code if you really want better help
A couple of ideas (more like heuristics):
1) Examine the fields of the class. If a group of fields is only used in a few methods, that might be a sign that that group of fields and the methods that use it might belong in another class.
2) Assuming a well-named class, compare the name of the class to what the class actually does. If you find methods that do things above and beyond what you'd expect from the class' name, that might be a sign that those methods belong in a different class. For example, if your class represents a Customer but also opens, closes, and writes to a log file, break out the log file code into a Logger class. See also: Single Responsibility Principle (PDF) for some interesting ideas .
3) If some of the methods primarily call methods on one other class, that could be a sign that those methods should be moved to the class they're frequently using (e.g. Feature Envy).
CAUTION: Like they say, breaking up is hard to do. If there is risk in breaking up the class, you may want to put some tests in place so that you know you're not breaking anything as you refactor. Consider reading "Working Effectively with Legacy Code" and the "Refactoring" book.
you could break up by delegating functions to other helper classes.
but I agree that 300 lines of code isn't terrible.
+1 for posting the code
Thanks for the code.
Here are a few things you might try:
1) Refactor duplicate code. This kind of code was duplicated about seven times:
Visio.Cell pinX = GetLayoutCell(Visio.VisCellIndices.visXFormPinX);
if (pinX != null)
{
pinX.set_Result("cm", value);
}
Note: PinY also calculates pinX but doesn't use its value.
Similar duplication exists in: Pos{X,Y}{Start,End}
What makes this class more challenging to break up is that it's a wrapper around an already complex class.
Not knowing the domain very well (although I'm an expert with the Shape, Circle, Square concept), I'd be tempted to break the class into several classes that each share the same core Shape object.
Here is a sketch:
class EnvironShape {
private ShapeProperties _properties; // contains property management code
private ShapeCollection _children; // contains code for acting on children
private Decorators _decorators; // code for accessing decorators
private Layers _layers; // layer management code
private Position _position; // code for working with the shape's position
// Other code omitted
}
I would not immediately and directly expose these objects (e.g. public ShapeCollection GetChildren()) but I would start off making the EnvironShape delegate to these objects.
I asked a similar question yesterday that was specific to a technology, but now I find myself wondering about the topic in the broad sense.
For simplicity's sake, we have two classes, A and B, where B is derived from A. B truly "is a" A, and all of the routines defined in A have the same meaning in B.
Let's say we want to display a list of As, some of which are actually Bs. As we traverse our list of As, if the current object is actually a B, we want to display some of Bs additional properties....or maybe we just want to color the Bs differently, but neither A nor B have any notion of "color" or "display stuff".
Solutions:
Make the A class semi-aware of B by basically including a method called isB() in A that returns false. B will override the method and return true. Display code would have a check like: if (currentA.isB()) B b = currentA;
Provide a display() method in A that B can override.... but then we start merging the UI and the model. I won't consider this unless there is some cool trick I'm not seeing.
Use instanceof to check if the current A object to be displayed is really a B.
Just add all the junk from B to A, even though it doesn't apply to A. Basically just contain a B (that does not inherit from A) in A and set it to null until it applies. This is somewhat attractive. This is similar to #1 I guess w/ composition over inheritance.
It seems like this particular problem should come up from time to time and have an obvious solution.
So I guess the question maybe really boils down to:
If I have a subclass that extends a base class by adding additional functionality (not just changing the existing behavior of the base class), am I doing something tragically wrong? It all seems to instantly fall apart as soon as we try to act on a collection of objects that may be A or B.
A variant of option 2 (or hybrid of 1 and 2) may make sense: after all, polymorphism is the standard solution to "Bs are As but need to behave differently in situation X." Agreed, a display() method would probably tie the model to the UI too closely, but presumably the different renderings you want at the UI level reflect semantic or behavioural differences at the model level. Could those be captured in a method? For example, instead of an outright getDisplayColour() method, could it be a getPriority() (for example) method, to which A and B return different values but it is still up to the UI to decide how to translate that into a colour?
Given your more general question, however, of "how can we handle additional behaviour that we can't or won't allow to be accessed polymorphically via the base class," for example if the base class isn't under our control, your options are probably option 3, the Visitor pattern or a helper class. In both cases you are effectively farming out the polymorphism to an external entity -- in option 3, the UI (e.g. the presenter or controller), which performs an instanceOf check and does different things depending on whether it's a B or not; in Visitor or the helper case, the new class. Given your example, Visitor is probably overkill (also, if you were not able/willing to change the base class to accommodate it, it wouldn't be possible to implement it I think), so I'd suggest a simple class called something like "renderer":
public abstract class Renderer {
public static Renderer Create(A obj) {
if (obj instanceOf B)
return new BRenderer();
else
return new ARenderer();
}
public abstract Color getColor();
}
// implementations of ARenderer and BRenderer per your UI logic
This encapsulates the run-time type checking and bundles the code up into reasonably well-defined classes with clear responsibilities, without the conceptual overhead of Visitor. (Per GrizzlyNyo's answer, though, if your hierarchy or function set is more complex than what you've shown here, Visitor could well be more appropriate, but many people find Visitor hard to get their heads around and I would tend to avoid it for simple situations -- but your mileage may vary.)
The answer given by itowlson covers pretty well most part of the question. I will now deal with the very last paragraph as simply as I can.
Inheritance should be implemented for reuse, for your derived class to be reused in old code, not for your class reusing parts of the base class (you can use aggregation for that).
From that standpoint, if you have a class that is to be used on new code with some new functionality, but should be used transparently as a former class, then inheritance is your solution. New code can use the new functionality and old code will seamlessly use your new objects.
While this is the general intention, there are some common pitfals, the line here is subtle and your question is about precisely that line. If you have a collection of objects of type base, that should be because those objects are meant to be used only with base's methods. They are 'bases', behave like bases.
Using techniques as 'instanceof' or downcasts (dynamic_cast<>() in C++) to detect the real runtime type is something that I would flag in a code review and only accept after having the programmer explain to great detail why any other option is worse than that solution. I would accept it, for example, in itowlson's answer under the premises that the information is not available with the given operations in base. That is, the base type does not have any method that would offer enough information for the caller to determine the color. And if it does not make sense to include such operation: besides the prepresentation color, are you going to perform any operation on the objects based on that same information? If logic depends on the real type, then the operation should be in base class to be overriden in derived classes. If that is not possible (the operation is new and only for some given subtypes) there should at least be an operation in the base to allow the caller to determine that a downcast will not fail. And then again, I would really require a sound reason for the caller code to require knowledge of the real type. Why does the user want to see it in different colors? Will the user perform different operations on each one of the types?
If you endup requiring to use code to bypass the type system, your design has a strange smell to it. Of course, never say never, but you can surely say: avoid depending on instanceof or downcasts for logic.
This looks like text book case for the Visitor design pattern (also known as "Double Dispatch").
See this answer for link to a thorough explanation on the Visitor and Composite patterns.
Can anyone think of any situation to use multiple inheritance? Every case I can think of can be solved by the method operator
AnotherClass() { return this->something.anotherClass; }
Most uses of full scale Multiple inheritance are for mixins. As an example:
class DraggableWindow : Window, Draggable { }
class SkinnableWindow : Window, Skinnable { }
class DraggableSkinnableWindow : Window, Draggable, Skinnable { }
etc...
In most cases, it's best to use multiple inheritance to do strictly interface inheritance.
class DraggableWindow : Window, IDraggable { }
Then you implement the IDraggable interface in your DraggableWindow class. It's WAY too hard to write good mixin classes.
The benefit of the MI approach (even if you are only using Interface MI) is that you can then treat all kinds of different Windows as Window objects, but have the flexibility to create things that would not be possible (or more difficult) with single inheritance.
For example, in many class frameworks you see something like this:
class Control { }
class Window : Control { }
class Textbox : Control { }
Now, suppose you wanted a Textbox with Window characteristics? Like being dragable, having a titlebar, etc... You could do something like this:
class WindowedTextbox : Control, IWindow, ITexbox { }
In the single inheritance model, you can't easily inherit from both Window and Textbox without having some problems with duplicate Control objects and other kinds of problems. You can also treat a WindowedTextbox as a Window, a Textbox, or a Control.
Also, to address your .anotherClass() idiom, .anotherClass() returns a different object, while multiple inheritance allows the same object to be used for different purposes.
I find multiple inheritance particularly useful when using mixin classes.
As stated in Wikipedia:
In object-oriented programming
languages, a mixin is a class that
provides a certain functionality to be
inherited by a subclass, but is not
meant to stand alone.
An example of how our product uses mixin classes is for configuration save and restore purposes. There is an abstract mixin class which defines a set of pure virtual methods. Any class which is saveable inherits from the save/restore mixin class which automatically gives them the appropriate save/restore functionality.
But they may also inherit from other classes as part of their normal class structure, so it is quite common for these classes to use multiple inheritance in this respect.
An example of multiple inheritance:
class Animal
{
virtual void KeepCool() const = 0;
}
class Vertebrate
{
virtual void BendSpine() { };
}
class Dog : public Animal, public Vertebrate
{
void KeepCool() { Pant(); }
}
What is most important when doing any form of public inheritance (single or multiple) is to respect the is a relationship. A class should only inherit from one or more classes if it "is" one of those objects. If it simply "contains" one of those objects, aggregation or composition should be used instead.
The example above is well structured because a dog is an animal, and also a vertebrate.
Most people use multiple-inheritance in the context of applying multiple interfaces to a class. This is the approach Java and C#, among others, enforce.
C++ allows you to apply multiple base classes fairly freely, in an is-a relationship between types. So, you can treat a derived object like any of its base classes.
Another use, as LeopardSkinPillBoxHat points out, is in mix-ins. An excellent example of this is the Loki library, from Andrei Alexandrescu's book Modern C++ Design. He uses what he terms policy classes that specify the behavior or the requirements of a given class through inheritance.
Yet another use is one that simplifies a modular approach that allows API-independence through the use of sister-class delegation in the oft-dreaded diamond hierarchy.
The uses for MI are many. The potential for abuse is even greater.
Java has interfaces. C++ has not.
Therefore, multiple inheritance can be used to emulate the interface feature.
If you're a C# and Java programmer, every time you use a class that extends a base class but also implements a few interfaces, you are sort of admitting multiple inheritance can be useful in some situations.
I think it would be most useful for boilerplate code. For example, the IDisposable pattern is exactly the same for all classes in .NET. So why re-type that code over and over again?
Another example is ICollection. The vast majority of the interface methods are implemented exactly the same. There are only a couple of methods that are actually unique to your class.
Unfortunately multiple-inheritance is very easy to abuse. People will quickly start doing silly things like LabelPrinter class inherit from their TcpIpConnector class instead of merely contain it.
One case I worked on recently involved network enabled label printers. We need to print labels, so we have a class LabelPrinter. This class has virtual calls for printing several different labels. I also have a generic class for TCP/IP connected things, which can connect, send and receive.
So, when I needed to implement a printer, it inherited from both the LabelPrinter class and the TcpIpConnector class.
I think fmsf example is a bad idea. A car is not a tire or an engine. You should be using composition for that.
MI (of implementation or interface) can be used to add functionality. These are often called mixin classes.. Imagine you have a GUI. There is view class that handles drawing and a Drag&Drop class that handles dragging. If you have an object that does both you would have a class like
class DropTarget{
public void Drop(DropItem & itemBeingDropped);
...
}
class View{
public void Draw();
...
}
/* View you can drop items on */
class DropView:View,DropTarget{
}
It is true that composition of an interface (Java or C# like) plus forwarding to a helper can emulate many of the common uses of multiple inheritance (notably mixins). However this is done at the cost of that forwarding code being repeated (and violating DRY).
MI does open a number of difficult areas, and more recently some language designers have taken decisions that the potential pitfalls of MI outweigh the benefits.
Similarly one can argue against generics (heterogeneous containers do work, loops can be replaced with (tail) recursion) and almost any other feature of programming languages. Just because it is possible to work without a feature does not mean that that feature is valueless or cannot help to effectively express solutions.
A rich diversity of languages, and language families makes it easier for us as developers to pick good tools that solve the business problem at hand. My toolbox contains many items I rarely use, but on those occasions I do not want to treat everything as a nail.
An example of how our product uses mixin classes is for configuration save and restore purposes. There is an abstract mixin class which defines a set of pure virtual methods. Any class which is saveable inherits from the save/restore mixin class which automatically gives them the appropriate save/restore functionality.
This example doesn't really illustrate the usefulness of multiple inheritance. What being defined here is an INTERFACE. Multiple inheritance allows you to inherit behavior as well. Which is the point of mixins.
An example; because of a need to preserve backwards compatibility I have to implement my own serialization methods.
So every object gets a Read and Store method like this.
Public Sub Store(ByVal File As IBinaryWriter)
Public Sub Read(ByVal File As IBinaryReader)
I also want to be able to assign and clone object as well. So I would like this on every object.
Public Sub Assign(ByVal tObject As <Class_Name>)
Public Function Clone() As <Class_Name>
Now in VB6 I have this code repeated over and over again.
Public Assign(ByVal tObject As ObjectClass)
Me.State = tObject.State
End Sub
Public Function Clone() As ObjectClass
Dim O As ObjectClass
Set O = New ObjectClass
O.State = Me.State
Set Clone = 0
End Function
Public Property Get State() As Variant
StateManager.Clear
Me.Store StateManager
State = StateManager.Data
End Property
Public Property Let State(ByVal RHS As Variant)
StateManager.Data = RHS
Me.Read StateManager
End Property
Note that Statemanager is a stream that read and stores byte arrays.
This code is repeated dozens of times.
Now in .NET i am able to get around this by using a combination of generics and inheritance. My object under the .NET version get Assign, Clone, and State when they inherit from MyAppBaseObject. But I don't like the fact that every object inherits from MyAppBaseObject.
I rather just mix in the the Assign Clone interface AND BEHAVIOR. Better yet mix in separately the Read and Store interface then being able to mix in Assign and Clone. It would be cleaner code in my opinion.
But the times where I reuse behavior are DWARFED by the time I use Interface. This is because the goal of most object hierarchies are NOT about reusing behavior but precisely defining the relationship between different objects. Which interfaces are designed for. So while it would be nice that C# (or VB.NET) had some ability to do this it isn't a show stopper in my opinion.
The whole reason that this is even an issue that that C++ fumbled the ball at first when it came to the interface vs inheritance issue. When OOP debuted everybody thought that behavior reuse was the priority. But this proved to be a chimera and only useful for specific circumstances, like making a UI framework.
Later the idea of mixins (and other related concepts in aspect oriented programming) were developed. Multiple inheritance was found useful in creating mix-ins. But C# was developed just before this was widely recognized. Likely an alternative syntax will be developed to do this.
I suspect that in C++, MI is best use as part of a framework (the mix-in classes previously discussed). The only thing I know for sure is that every time I've tried to use it in my apps, I've ended up regretting the choice, and often tearing it out and replacing it with generated code.
MI is one more of those 'use it if you REALLY need it, but make sure you REALLY need it' tools.
The following example is mostly something I see often in C++: sometimes it may be necessary due to utility classes that you need but because of their design cannot be used through composition (at least not efficiently or without making the code even messier than falling back on mult. inheritance). A good example is you have an abstract base class A and a derived class B, and B also needs to be a kind of serializable class, so it has to derive from, let's say, another abstract class called Serializable. It's possible to avoid MI, but if Serializable only contains a few virtual methods and needs deep access to the private members of B, then it may be worth muddying the inheritance tree just to avoid making friend declarations and giving away access to B's internals to some helper composition class.
I had to use it today, actually...
Here was my situation - I had a domain model represented in memory where an A contained zero or more Bs(represented in an array), each B has zero or more Cs, and Cs to Ds. I couldn't change the fact that they were arrays (the source for these arrays were from automatically generated code from the build process). Each instance needed to keep track of which index in the parent array they belonged in. They also needed to keep track of the instance of their parent (too much detail as to why). I wrote something like this (there was more to it, and this is not syntactically correct, it's just an example):
class Parent
{
add(Child c)
{
children.add(c);
c.index = children.Count-1;
c.parent = this;
}
Collection<Child> children
}
class Child
{
Parent p;
int index;
}
Then, for the domain types, I did this:
class A : Parent
class B : Parent, Child
class C : Parent, Child
class D : Child
The actually implementation was in C# with interfaces and generics, and I couldn't do the multiple inheritance like I would have if the language supported it (some copy paste had to be done). So, I thought I'd search SO to see what people think of multiple inheritance, and I got your question ;)
I couldn't use your solution of the .anotherClass, because of the implementation of add for Parent (references this - and I wanted this to not be some other class).
It got worse because the generated code had A subclass something else that was neither a parent or a child...more copy paste.