5.6 Configuración del diagnóstico avanzado de bus de campo con SIMATIC PDM
5.6.3 Configuración manual del diagnóstico avanzado de bus de campo
7 { return perimeter( ) / 2; }
2. Abstract methods. Overriding is resolved at run time. The base class provides no implementation and is abstract. The absence of a default requires either that the derived classes provide an implementation or that the classes themselves be abstract.
3. Static methods. Overridding is resolved at compile time because there is no controlling object.
4. Other methods. Overriding is resolved at run time. The base class provides a default implementation that may be either overridden by the derived classes or accepted unchanged by the derived classes.
4.2.2
designing for the future
Consider the following implementation for the Square class:
public class Square extends Rectangle {
public Square( double side ) { super( side, side ); } }
Since obviously a square is a rectangle whose length and width are the same, it would seem reasonable to have Square extend Rectangle, and thus avoid rewriting methods such as area and perimeter. While it is true that becausetoStringis not overridden, Squareswill always be output as Rectangles
with identical lengths and widths, that can be repaired by providing a toString
method for Square. Thus the Squareclass can be made slick and we can reuse
Rectanglecode. But is this a reasonable design? To answer that question, we must go back to the fundamental rule of inheritance.
Theextends clause is appropriate only if it is true that SquareIS-ARectangle. From a programming perspective, this does not simply mean that a square must geometrically be a type of rectangle; rather, it means that any operation that a Rectangle can perform must also be able to be supported by a Square. Most important, however, this is not a static decision, meaning that we do not simply look at the current set of operations supported by Rectangle. Rather, we must ask if it is reasonable to assume that in the future it is possible that operations might be added to the Rectangle class that would not make sense for a Square. If that is the case, then the argument that a Square IS-A Rectangle is weakened considerably. For instance, suppose the Rectangle class has a stretch method whose contract provides that stretch lengths the larger dimension of the Rectangle, while leaving the smaller dimension in tact. Clearly the operation cannot be made available to a Square, since doing so would destroy squareness.
Multiple inheritance
is used to derive a class from several base classes. Java does not allow mul- tiple inheritance.
If we know that the Rectangleclass has a stretchmethod, then it is proba- bly not a good design to have Square extend Rectangle. If Square already extendsRectangle and then later on we want to add stretch to Rectangle, there are two basic ways to proceed.
Option #1 would be to have Squareoverridestretchwith an implementa- tion that throws an exception:
public void stretch( double factor )
{ throw new UnsupportedOperationException( ); }
With this design, at least squares will never lose their squareness.
Option #2 would be to redesign the entire hierarchy to have Square no longer extend Rectangle. This is known as refactoring. Depending on how complicated the entire hierarchy is, this could be an incredibly messy task. However, some development tools can automate much of the process. The best plan, especially for a large hierarchy is to think about these issues at the time of design, and ask what the hierarchy might reasonably look like in the future. Often this is easy to say, but very challenging to do.
A similar philosophy occurs when deciding what exceptions should be listed in the throws list of a method. Because of the IS-A relationship, when a method is overridden, new checked exceptions cannot be added to the throws list. The overriding implementation can reduce, or subset, the original list of checked exceptions, but can never add to it. As such, in determining the throws list of a method, the designer should look not only at the exceptions that can be thrown in the current implementation of the method, but also what exceptions might reasonably be thrown by the method in the future (should the implementation change) and what exceptions might be thrown by overrid- ing implementations provided by future subclasses.
4.3
multiple inheritance
All the inheritance examples seen so far derived one class from a single base class. In multiple inheritance, a class may be derived from more than one base class. For instance, we may have a Student class and an Employee class. A
StudentEmployee could then be derived from both classes.
Although multiple inheritance sounds attractive, and some languages (including C++) support it, it is wrought with subtleties that make design difficult. For instance, the two base classes may contain two methods that have the same signature but different implementations. Alternatively, they may have two identically named fields. Which one should be used?
For example, suppose that in the previous StudentEmployeeexample,Person
is a class with data field nameand method toString. Suppose, too, that Student
extendsPersonand overrides toStringto include the year of graduation. Further, suppose that EmployeeextendsPersonbut does not override toString; instead, it declares that it is final.
1. Since StudentEmployee inherits the data members from both Student
andEmployee, do we get two copies of name?
2. IfStudentEmployee does not override toString, which toString method should be used?
When many classes are involved, the problems are even larger. It appears, however, that the typical multiple inheritance problems can be traced to con- flicting implementations or conflicting data fields. As a result, Java does not allow multiple inheritance of implementations.
However, allowing multiple inheritance for the purposes of type- compatibility can be very useful, as long as we can ensure that there are no implementation conflicts.
Returning to our Shape example, suppose our hierarchy contains many shapes such as Circle, Square,Ellipse,Rectangle,Triangle. Suppose that for some, but not all of these shapes, we have a stretch method, as described in Section 4.2.2 that lengthens the longest dimension, leaving all others unchanged. We could reasonably envision that the stretchmethod is written forEllipse,Rectangle, and Triangle, but not Circle or Square. We would like a method to stretch all the shapes in an array:
public static void stretchAll( WhatType [ ] arr, factor ) {
for( WhatType s : arr ) s.stretch( factor ); }
The idea is that stretchAll would work for arrays of Ellipse, arrays of
Rectangle, arrays of Triangle, or even an array that contained Ellipses,Rectangles, andTriangles.
For this code to work, we need to decide the type declaration for
WhatType. One possibility is that WhatTypecan be Shape, as long as Shapehas an abstract stretch method. We could then override stretchfor each type of Shape, having Circle and Square throw UnsupportedOperationExceptions. But as we discussed in Section 4.2.2, this solution seems to violate the notion of an IS-A relationship, and moreover, it does not generalize out to more complicated cases.
Another idea would be to try to define an abstract class Stretchable as follows:
abstract class Stretchable {
public abstract void stretch( double factor ); }
We could use Stretchable as our missing type in the stretchAllmethod. At that point, we would try to have Rectangle,Ellipses, and Triangle extend Stretchable, and provide the stretch method:
// Does not work
public class Rectangle extends Shape, Stretchable {
public void stretch( double factor ) { ... }
public void area( ) { ... }
... }
The picture that we would have at this point is shown in Figure 4.15.
In principle this would be fine, but then we have multiple inheritance, which we have previously said was illegal, because of concerns that we might inherit conflicting implementations. As it stands now, only the Shape
class has an implementation; Stretchable is purely abstract, so one could argue that the compiler should be willing to grant leniency. But it is possible that after everything is compiled, Stretchablecould be altered to provide an
Shape
Circle Square Rectangle Ellipse Triangle
Stretchable
figure 4.15
Inheriting multiple classes. This does not work unless either ShapeorStretchableis specifically designated as being implementation-free
implementation, at which point there would be a problem. What we would like is more than a campaign promise; we need some syntax that forces
Stretchableto remain implementation-free forever. If this was possible, then the compiler could allow the inheritance from two classes that has a hierar- chy in the style of Figure 4.15.
This syntax is precisely what an interface is.
4.4
the interface
The interface is an abstract class that contains no imple- mentation details.
The interface in Java is the ultimate abstract class. It consists of public abstract methods and public static final fields, only.
A class is said to implement the interface if it provides definitions for all of the abstract methods in the interface. A class that implements the interface behaves as if it had extended an abstract class specified by the interface.
In principle, the main difference between an interface and an abstract class is that although both provide a specification of what the subclasses must do, the interface is not allowed to provide any implementation details either in the form of data fields or implemented methods. The practical effect of this is that multiple interfaces do not suffer the same potential problems as multiple inheritance because we cannot have conflicting imple- mentations. Thus, while a class may extend only one other class, it may implement more than one interface.
4.4.1
specifying an interface
Syntactically, virtually nothing is easier than specifying an interface. The inter- face looks like a class declaration, except that it uses the keyword interface. It consists of a listing of the methods that must be implemented. An example is theStretchable interface, shown in Figure 4.16.
The Stretchable interface specifies one method that every subclass must implement: Stretch. Note that we do not have to specify that these methods are public and abstract. Since these modifiers are required for interface methods, they can and usually are omitted.
figure 4.16
TheStretchable interface
1 /**
2 * Interface that defines stretch method to lengthen the longest
3 * dimension of a Shape
4 */
5 public interface Stretchable
6 {