In inheritance, what if the subclass does not adhere to the behavior of the superclass?

As with the Mammals class, there is walking behavior that all subclasses should apply to.

But there are several mammals, such as Dolphin and Bath, that do not have this behavior.

How can we do this?

According to me, all subclasses must adhere to all the behavior associated with the superclass.

Any help is appreciated. Thanks!

+4
source share
8 answers

The Mammal class should only define general characteristics for all mammals, as you said that walking is not a common feature.

Behavior can be added using interfaces, for example, in the following example.

class abstract Mammal { abstract void regulateTemperature(); } interface CanFly { void land(); void takeOff(); } class Bat extends Mammal implements CanFly { } 

Sorry if I made syntax errors, my Java is a little rusty, but you have an idea, just be as general as you can in your base class. I said that I agree with @dystroy, it is too difficult to get the right to inherit from the domain of animals. You can try modeling a lamp or shirt to start with something simpler than this.

+6
source

Your statements contradict each other.

  • As in the Mammals class, walking behavior is observed that all subclasses must adhere to.
  • But there are several mammals, such as Dolphin and Bath, that do not have this behavior.

Either all subclasses have behavior, or not all have behavior. You cannot have both.

In an object-oriented design, it is useful that all subclasses support the contracts of their superclass, so that an instance of any subclass can be used anywhere the superclass refers to. This is called the Liskov replacement principle .

+2
source

You have just discovered a fundamental problem with the concept of traditional inheritance and OOP. Classifying objects into strict categories is extremely difficult even in the most trivial examples (interestingly, classification is a large part of IQ tests). When studying the example of the animal world, it quickly becomes apparent that the time of grouping into strict, from top to bottom, dividing categories does not make sense. Combine this idea with programming and try to reuse functionality, and you can end up killing yourself.

Modern OOP avoids using inheritance to reuse code, and instead uses it for polymorphism. Trees with deep inheritance are fragile and are considered bad practice. Code reuse instead is done through aggregation. Small objects and their behavior are mixed and matched to create much more complex objects. This behavior is enhanced through concepts such as dependency injection and policy development.

For more information and practical applications of these concepts, read:

http://en.wikipedia.org/wiki/Composition_over_inheritance

http://en.wikipedia.org/wiki/Aspect-oriented_programming

http://en.wikipedia.org/wiki/Component-based_software_engineering

http://en.wikipedia.org/wiki/Policy-based_design

http://en.wikipedia.org/wiki/Dependency_injection

+2
source

Simple, use the Walking interface, which you can use for animals that walk.

For instance:

 interface Walking { public abstract void walk(); // implementing classes must implement this } class Cow extends Mammal implements Walking { public void walk() { ... } } class Dolphin extends Mammal { public void swim() { ... } } class Bat extends Mammal { public void fly() { ... } } 
0
source

The Mammal class in your example is not defined correctly, since not all mammals can walk. It should not include the walk method. Instead, I would choose the Walking interface, with the Swimming and Flying interfaces, as well as for other methods used for moving.

0
source

If you define Mammal as the Walk () method, you say that all mammals can walk.

Your implementation for Dolphin might look like this:

 public void Walk() { throw new TraitLossException(); } 

http://www.nescent.org/science/awards_summary.php?id=24

0
source

Disclaimer: This answer is not about good design, but about existing practice.

Sometimes you have a subclass that cannot (or simply will not) provide all the services offered by the superclass. One striking example would be Iterator.remove (), which may or may not be implemented. When this situation appears in standard libraries, an UnsupportedOperationException is usually thrown. In some cases, as an iterator, to some extent even part of the contract is that an implementation that does not support the operation must throw an exception.

0
source

This is one of those cases where it makes sense to subclass a non-abstract class.

 class Mammal { ... /** May not walk. This implementation succeeds. */ void walk() { ... do some walking ... } } class WateronlyMammal extends Mammal { @Override void walk() { ... sit there looking sad ... } } 

Then create animal types like new Mammal("Dog") or new WateronlyMammal("Dolphin") .

An alternative you may need is a composition instead of inheritance that trades verbosity for simpler components.

  interface Walker { /** May not walk. */ void walk(); } final class Mammal { public Mammal(String speciesName, Walker walk) { ... } ... } 

Creation as new Mammal("Dog", competentWalker()) or new Mammal("Dolphin", notSoGoodWalker()) .

May even add convenience constructors:

  public Mammal(String speciesName) { this(speciesName, competentWalker(), poorFlyer()); } 

(Note that we have some confusion here with the type of species and the particular animal. It is also worth noting that if you take every animal that has ever existed, there are no species boundaries.)

0
source

Source: https://habr.com/ru/post/1490715/


All Articles