Sunday, May 28, 2017

Introduction to Java programming, Part 2 (5)

Inheritance


You've encountered examples of inheritance a few times already in this tutorial. This section reviews some of Part 1's material on inheritance and explains in more detail how inheritance works — including the inheritance hierarchy, constructors and inheritance, and inheritance abstraction.

How inheritance works

Classes in Java code exist in chains of importance. Classes over a given class in a chain of importance are superclasses of that class. That specific class is a subclass of each class higher up the progressive system. A subclass acquires from its superclasses. The java.lang.Object class is at the highest point of the class progression — so every Java class is a subclass of, and acquires from, Object.
For example, suppose you have a Person class that looks like the one in Listing 14.
Listing 14. Public Person class
public class Person {
   
  public static final String STATE_DELIMITER = "~";
   
  public Person() {
    // Default constructor
  }
   
  public enum Gender {
    MALE,
    FEMALE,
    UNKNOWN
  }
   
  public Person(String name, int age, int height, int weight, String eyeColor, Gender gender) {
    this.name = name;
    this.age = age;
    this.height = height;
    this.weight = weight;
    this.eyeColor = eyeColor;
    this.gender = gender;
  }
  private String name;
  private int age;
  private int height;
  private int weight;
  private String eyeColor;
  private Gender gender;
The Person class in Listing 14 implicitly inherits from Object. Because inheriting from Object is assumed for every class, you don't need to type extends Object for every class you define. But what does it mean to say that a class inherits from its superclass? It simply means that Person has access to the exposed variables and methods in its superclasses. In this case, Person can see and use Object's public and protected methods and variables.

Defining a class hierarchy

Now suppose you have an Employee class that inherits from Person. Employee's class definition would look something like this:
public class Employee extends Person {

  private String taxpayerIdentificationNumber;
  private String employeeNumber;
  private BigDecimal salary;
  // . . .
}
The Employee legacy relationship to the greater part of its superclasses (its legacy chart) suggests that Employee approaches all open and secured factors and techniques in Person (since Employee straightforwardly broadens Person), and also those in Object (since Employee really develops Object, as well, however in a roundabout way). Be that as it may, in light of the fact that Employee and Person are in a similar bundle, Employee additionally approaches the bundle private (at times called well disposed) factors and strategies in Person.
To go one step deeper into the class hierarchy, you could create a third class that extends Employee:
public class Manager extends Employee {
  // . . .
}
In the Java language, any class can have at most one direct superclass, but a class can have any number of subclasses. That's the most important thing to remember about inheritance hierarchy in the Java language.

Single versus multiple inheritance

Dialects like C++ bolster the idea of different legacy: At any point in the chain of command, a class can specifically acquire from at least one classes. The Java dialect underpins just single legacy—which means you can just utilize the develops catchphrase with a solitary class. So the class chain of command for any Java class dependably comprises of a straight line as far as possible up to java.lang.Object. Be that as it may, as you'll learn in the following principle area, Interfaces, the Java dialect underpins executing different interfaces in a solitary class, giving you a workaround of sorts to single legacy.

Constructors and inheritance

Constructors aren't full-fledged object-oriented members, so they aren't inherited; instead, you must explicitly implement them in subclasses. Before I go into that topic, I'll review some basic rules about how constructors are defined and invoked.

Constructor basics

Remember that a constructor always has the same name as the class it's used to construct, and it has no return type. For example:
public class Person {
  public Person() {
  }
}
Every class has at least one constructor, and if you don't explicitly define a constructor for your class, the compiler generates one for you, called the default constructor. The preceding class definition and this one are identical in how they function:
public class Person {
}

Invoking a superclass constructor

To invoke a superclass constructor other than the default constructor, you must do so explicitly. For example, suppose Person has a constructor that takes just the name of the Person object being created. From Employee's default constructor, you could invoke the Person constructor shown in Listing 15.
Listing 15. Initializing a new Employee
public class Person {
  private String name;
  public Person() {
  }
  public Person(String name) {
    this.name = name;
  }
}
// Meanwhile, in Employee.java
public class Employee extends Person {
  public Employee() {
    super("Elmer J Fudd");
  }
}
You would probably never want to initialize a new Employee object this way, however. Until you get more comfortable with object-oriented concepts, and Java syntax in general, it's a good idea to implement superclass constructors in subclasses only if you are sure you'll need them. Listing 16 defines a constructor in Employee that looks like the one in Person so that they match up. This approach is much less confusing from a maintenance standpoint.
Listing 16. Invoking a superclass
public class Person {
  private String name;
  public Person(String name) {
    this.name = name;
  }
}
// Meanwhile, in Employee.java
public class Employee extends Person {
  public Employee(String name) {
    super(name);
  }
}

Declaring a constructor

The first thing a constructor does is invoke the default constructor of its immediate superclass, unless you — on the first line of code in the constructor — invoke a different constructor. For example, the following two declarations are functionally identical:
public class Person {
  public Person() {
  }
}
// Meanwhile, in Employee.java
public class Employee extends Person {
  public Employee() {
  }
}
public class Person {
  public Person() {
  }
}
// Meanwhile, in Employee.java
public class Employee extends Person {
  public Employee() {
  super();
  }
}

No-arg constructors

If you provide an alternate constructor, you must explicitly provide the default constructor; otherwise it is unavailable. For example, the following code gives you a compile error:
public class Person {
  private String name;
  public Person(String name) {
    this.name = name;
  }
}
// Meanwhile, in Employee.java
public class Employee extends Person {
  public Employee() {
  }
}
The Person class in this example has no default constructor, because it provides an alternate constructor without explicitly including the default constructor.

How constructors invoke constructors

A constructor can invoke another constructor in the same class via the this keyword, along with an argument list. Like super(), the this() call must be the first line in the constructor, as in this example:
public class Person {
  private String name;
  public Person() {
    this("Some reasonable default?");
  }
  public Person(String name) {
    this.name = name;
  }
}
You see this idiom frequently. One constructor delegates to another, passing in a default value if that constructor is invoked. This technique is also a great way to add a new constructor to a class while minimizing impact on code that already uses an older constructor.

Constructor access levels

Constructors can have any access level you want, and certain rules of visibility apply. Table 1 summarizes the rules of constructor access.
Table 1. Constructor access rules
Constructor access modifierDescription
publicConstructor can be invoked by any class.
protectedConstructor can be invoked by an class in the same package or any subclass.
No modifier ( package-private)Constructor can be invoked by any class in the same package.
privateConstructor can be invoked only by the class in which the constructor is defined.
You might be able to think of use cases in which constructors would be declared protected or even package-private, but how is a private constructor useful? I've used private constructors when I didn't want to allow direct creation of an object through the new keyword when implementing, say, the Factory pattern. In that case, I'd use a static method to create instances of the class, and that method — being included in the class — would be allowed to invoke the private constructor.

Inheritance and abstraction

In the event that a subclass abrogates a strategy from a superclass, the technique is basically shrouded in light of the fact that calling it through a reference to the subclass conjures the subclass' variant of the strategy, not the superclass' adaptation. Be that as it may, the superclass strategy is as yet open. The subclass can summon the superclass technique by introducing the name of the strategy with the super watchword (and not at all like with the constructor runs, this should be possible from any line in the subclass strategy, or even in an alternate strategy through and through). As a matter of course, a Java program calls the subclass strategy if it's summoned through a reference to the subclass. 

This capacity likewise applies to factors, gave the guest approaches the variable (that is, the variable is obvious to the code attempting to get to it). This detail can bring about you no end of despondency as you pick up capability in Java programming. Overshadow gives adequate notices — for instance, that you're concealing a variable from a superclass, or that a technique call won't call what you think it will. 

In an OOP setting, reflection alludes to summing up information and conduct to a sort higher up the legacy chain of command than the present class. When you move factors or strategies from a subclass to a superclass, you say you are abstracting those individuals. The principle explanation behind abstracting is to reuse normal code by driving it as far up the progressive system as could be expected under the circumstances. Having regular code in one place makes it less demanding to keep up.

Abstract classes and methods

Now and again, you need to make classes that exclusive fill in as reflections and don't really ever should be instantiated. Such classes are called unique classes. By a similar token, now and again certain strategies should be actualized diversely for every subclass that executes the superclass. Such strategies are dynamic techniques. Here are some essential tenets for dynamic classes and strategies:

  • Any class can be declared abstract.
  • Abstract classes cannot be instantiated.
  • An abstract method cannot contain a method body.
  • Any class with an abstract method must be declared abstract.

Using abstraction

Suppose you don't want to allow the Employee class to be instantiated directly. You simply declare it using the abstract keyword, and you're done:
public abstract class Employee extends Person {
  // etc.
}
If you try to run this code, you get a compile error:
public void someMethodSomwhere() {
  Employee p = new Employee();// compile error!!
}
The compiler is complaining that Employee is abstract and can't be instantiated.

The power of abstraction

Assume that you require a strategy to analyze the condition of an Employee protest and ensure that it's substantial. This need would appear to be normal to all Employee objects, however it would have zero potential for reuse in light of the fact that it would act diversely among every single potential subclass. All things considered, you announce the approve() technique theoretical (compelling all subclasses to actualize it):

public abstract class Employee extends Person {
  public abstract boolean validate();
}
Every direct subclass of Employee (such as Manager) is now required to implement the validate()method. However, once a subclass implements the validate() method, none of its subclasses need to implement it.
For example, suppose you have an Executive object that extends Manager. This definition would be valid:
public class Executive extends Manager {
  public Executive() {
  }
}

When (not) to abstract: Two rules

As a first general guideline, don't digest in your underlying outline. Utilizing unique classes ahead of schedule in the plan compels you down a way that could confine your application. You can simply refactor regular conduct (which is the whole purpose of having conceptual classes) additionally up the legacy diagram — and it's quite often better to refactor after you've found that you do need to. Overshadow has brilliant support for refactoring. 

Second, as intense as dynamic classes seem to be, oppose utilizing them. Unless your superclasses contain much normal conduct and aren't significant all alone, let them remain nonabstract. Profound legacy charts can make code support troublesome. Consider the exchange off between classes that are too vast and viable code.

Assignments: Classes

You can assign a reference from one class to a variable of a type belonging to another class, but certain rules apply. Take a look at this example:
Manager m = new Manager();
Employee e = new Employee();
Person p = m; // okay
p = e; // still okay
Employee e2 = e; // yep, okay
e = m; // still okay
e2 = p; // wrong!
The goal variable must be of a supertype of the class having a place with the source reference, or else the compiler gives you a mistake. Whatever is on the correct side of the task must be a subclass or an indistinguishable class from the thing on the left. To put it another way: a subclass is more particular in reason than its superclass, so think about a subclass as being smaller than its superclass. What's more, a superclass, being more broad, is more extensive than its subclass. The control is this, you may never make a task that will limit the reference.
Now consider this example:
Manager m = new Manager();
Manager m2 = new Manager();
m = m2; // Not narrower, so okay
Person p = m; // Widens, so okay
Employee e = m; // Also widens
Employee e = p; // Narrows, so not okay!
Although an Employee is a Person, it's most definitely not a Manager, and the compiler enforces this distinction.
Previous Post
Next Post

post written by:

0 coment�rios: