Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АрхитектураБиологияГеографияДругоеИностранные языки
ИнформатикаИсторияКультураЛитератураМатематика
МедицинаМеханикаОбразованиеОхрана трудаПедагогика
ПолитикаПравоПрограммированиеПсихологияРелигия
СоциологияСпортСтроительствоФизикаФилософия
ФинансыХимияЭкологияЭкономикаЭлектроника

Defining methods of object creation (constructors)

Introduction to objects | The first program | Types. Primitive types. | Types of variables. Declarations. | More on operators and expressions | Numeric promotions | Objects and references | The class String | Useful examples | Defining attributes of objects |


Читайте также:
  1. Aims and Objectives
  2. Alternative Methods
  3. An indefinite object
  4. Anonymous object creation expressions
  5. Array creation expressions
  6. B) Complex Object (Objective Infinitive Construction)
  7. C) Defining the Operational Level Agreements for the technical teams

Object creation is a special operation carried out by means of the class instance creation expression new.
It consists in invocation of a constructor of the class.

A constructor is used to initialize fields of object.
A constructor is a special kind of method, which:

 

Similarly to a definition of a method, a definition of a constructor may be preceded with an access modifier specifying whether the constructor may be invoked from other classes.

The syntax of the definition of a constructor:

[ public ] class class_name {

// Definition of the constructor
[ access_modifier ] class_name(list_of_parameters) {
// constructor body
}
}

 

The class Pair may have the following constructors:

public class Pair { private int a; private int b; public Pair(int x, int y) { // The fields a and b are a = x; // initialized with the b = y; // values of arguments }...}


or:

public class Pair { private int a, b; public Pair(int x) { // The constructor has one parameter a = x; // which initializes both fields b = x; }...}


A class may have many constructors with different lists of parameters. It is equivalent to method overloading.

Using the above constructors we can easily create objects of the class Pair which are initialized with the given values:

Pair p1 = new Pair(10,11); // a pair 10, 11
Pair p2 = new Pair(2); //a pair 2, 2

 

Constructors are always invoked by means of the class instance creation expression new.

 


A special constructor is the one which has no parameters.
It is automatically added to a class definition when there are no other constructors defined. The body of the default constructor is empty. Thus, if we do not create any constructor in a class, then by class instance creation the generated default constructor will be invoked.

Note: the default constructor is not generated if there is some other constructor defined in the class.

 

Example

Let us assume we need a program for managing a bookshop. The bookshop sells publications (books, journals, compact discs). Therefore, we are interested in publications in general.
Each publication has:
a title
a publisher
the year of publishing
an identification number (ISBN, ISSN or other)
a price
a number of copies

All these attributes are fields of the class.

public class Publication { private String title; private String publisher; private int year; private String ident; private double price; private int quantity;...}

Each publication is an object in our program. Objects must be initialized somehow. To ensure this we must supply a constructor which initializes fields of an object with the given parameters.

public class Publication { private String title; private String publisher; private int year; private String ident; private double price; private int quantity; public Publication(String t, String pb, int y, String i, double pr, int q) { title = t; // the field title is initialized with the value of that parameter t publisher = pb; // the file publisher is initialized with the value of the parameter pb year = y; // and so on... ident = i; price = pr; quantity = q; }...}

Now we are able to create an object representing a book, for example entitled "Cats", published by "Dog & Sons", which costs 21.0 EUR.

Publication b = new Publication("Cats", "Dog & Sons", 2002, "ISBN6789", 21.0, 0);

What can we do with publications?
We can buy them or sell them. We can ask for some information concerning the publication, like its title, publisher, year, identification or we may want to know how many copies there are in stock. It may happen that the price of a publication has changed, so we must have a way of modifying the object representing it.

All these operations on publications are defined as methods.

public class Publication {... // methods: public String getTitle() { return title; } public String getPublisher() { return publisher; } public int getYear() { return year; } public String getIdent() { return ident; } public double getPrice() { return price; } public void setPrice(double p) { price = p; } public int getQuantity() { return quantity; } public void buy(int n) { quantity += n; } public void sell(int n) { quantity -= n; }}


We test the class Publication in another class named TestPub (in its method main).

class PubTest { public static void main(String[] args) { // instance creation Publication b = new Publication("Cats", "Dog & Sons", 2002, "ISBN6789", 21.0, 0); int n = 10; // we buy 10 copies b.buy(n); double cost = n * b.getPrice(); // calculate the cost System.out.println("To buy " + n + " copies:"); System.out.println(b.getTitle()); System.out.println(b.getPublisher()); System.out.println(b.getYear()); System.out.println(b.getIdent()); System.out.println("---------------\n: " + cost + " EUR was spent"); // sell 4 copies and check how many was left b.sell(4); System.out.println("---------------"); System.out.println("There are " + b.getQuantity() + " copies left"); }}

To buy 10 copies:
Cats
Dog & Sons
2002
ISBN6789
---------------
210.0 EUR was spent
---------------
There are 6 copies left

Here is the output:

 


Inheritance

 

The inheritance allows reusing the functionality and the properties of an existing class by some other class, with possible modifications which make the new class more specialized.

 

The class Publication represents publications, but it does not represent books properly. Books are specialized kinds of publications. Besides all the properties of a publication (title, publisher, price, and so on), a book has one more property: the author (or authors).
Thus, to represent purchase and sale of books we need a class representing them. Let us call it Book.
We may define the class Book from scratch (defining the fields: author, title ident, price and methods operating on them as well as methods for selling and purchasing).
However, the class Publication supplies the most of the required attributes and methods.
Therefore, it is better to inherit the class Book from the class Publication. Of course, we must add the properties of books, which are absent in the class Publication.


The keyword extends expresses the inheritance of classes:

class A extends B {
...
}

means that the class B inherits (is derived) from the class A.
We say:

 

Let us define the class Book. Besides the properties of the superclass Publication we need a field storing the author of the book and a method returning its value.

class Book extends Publication { private String author; public String getAuthor() { return author; }}


Is it enough?
No, we need a constructor describing how instances of the class Book are initialized.
To create an object of this class we must supply the following information:

Thus the constructor should look like this:

public Book(String aut, String tit, String pub, int y, String id, double price, int quant) {....}

Unfortunately, the fields: title, publisher, year, ident, price and quantity have private access in the class Publication, so they are unavailable for us. How can we initialize them?

The fields of the superclass are to be initialized with the invocation of the constructor of the base class from the constructor of the derived class.

 


The following statement:

super(list_of_arguments);

is an invocation of a constructor from a superclass with the arguments given in list_of_arguments.
If it exists, such a statement must be the first instruction of the constructor of the derived class.
If it does not exist - the default constructor of the base class will be invoked before creating the object of the subclass.

 


The constructor of the class Book must invoke the constructor of the superclass to initialize its fields, and then initialize the field author.

// arguments: aut - author, tit - title, pub - publisher, y - year // id - ISBN, price - price, quant - quantity public Book(String aut, String tit, String pub, int y, String id, double price, int quant) { super(tit, pub, y, id, price, quant); author = aut; }

 

Now we can write full definition of the class Book:

public class Book extends Publication { private String author; public Book(String aut, String tit, String pub, int y, String id, double price, int quant) { super(tit, pub, y, id, price, quant); author = aut; } public String getAuthor() { return author; } }

and create an object:

Book b = new Book("James Gossling", "My Java", "WNT", 2002, "ISBN6893", 51.0, 0);

which stores:


Here is a test of the class Book:

class TestBook { public static void main(String[] args) { Book b = new Book("James Gossling", "My Java", "WNT", 2002, "ISBN6893", 51.0, 0); int n = 100; b.buy(n); double cost = n * b.getPrice(); System.out.println("To buy " + n + " books:"); System.out.println(b.getAuthor()); System.out.println(b.getTitle()); System.out.println(b.getPublisher()); System.out.println(b.getYear()); System.out.println(b.getIdent()); System.out.println("---------------\n" + cost + " EUR was spent"); b.sell(90); System.out.println("---------------"); System.out.println("There are " + b.getQuantity() + " copies left"); }}

To buy 100 books:
James Gossling
My Java
WNT
2002
ISBN6893
---------------
5100.0 EUR was spent
---------------
There are 10 copies left

which prints:

 

Objects of the class Book are objects of the class Publication as well
(they have the same properties).

 


Therefore, references of the type Book (referring to objects of the class Book) may be assigned to the variables of the type Publication (holding references to objects of the class Publication).

Book b = new Book(...);
Publication p = b;

It is called widening reference conversion.
Such conversions are applied automatically when:


The ability of acting as an object of another class is very useful.

Assume we derive a class Journal (besides the class Book) from the class Publication.
The class Journal inherits from Publication and has additional fields describing volume and number.
We might want to have some other sorts of publications too. For example, a class CDisk may inherit from Publication and represent compact disks.

Now we can write a single universal method calculating difference of income:

public double incomeDiff(Publication p1, Publication p2) { double income1 = p1.getQuantity() * p1.getPrice(); double income2 = p2.getQuantity() * p2.getPrice(); return income1 - income2;}


and invoke it for arbitrary types of publications:

Book b1 = new Book(...); Book b2 = new Book(...); Journal j = new Journal(...); CDisk cd1 = new CDisk(...); CDisk cd2 = new CDisk(...); double diff = 0; diff = incomeDiff(b1, b2); diff = incomeDifg(b1, j); diff = inocmeDiff(cd1, b1);


If there was no widening reference conversion, we would have to supply separate method for each pair of publications:
double incomeDiff(Book, Book),
double incomeDiff(Book, Journal),
double incomeDiff(Book, CDisk)
and so on...


Note that in the method incomeDiff we can send messages from the class Publication to objects denoted by p1 and p2, but we cannot send messages from its subclasses to them, even if objects denoted by p1 and p2 are objects of some subclasses of Publication.

....
{
Book b1 = new Book(...);
Book b2 = new Book(...);
someMethod(b1,b2);
....
}

void someMethod(Publication p1, Publication p2) {
String autor = p1.getAuthor(); // compilation error - type mismatch
... // there is no method getAuthor()
... // in the class Publication }

 

In Java each class may inherit from at most one superclass.
If we omit the keyword extends in the definition of a class, then derivation from the default class Object is assumed (as if we wrote class A extends Object).

 

The inheritance hierarchy of the discussed classes is shown on the figure.


A reference to an object of an arbitrary class may be assigned to a variable of the type Object (holding references to objects of the class Object).

 

 

Summary


The lecture presents classes. In particular we have learnt:

 

 

Exercises

  1. Define fields of a class describing rectangles. Supply a constructor initializing all the fields.
  2. Define a method which takes three integer numbers as arguments and returns their sum preceded by the string "The sum is: ".
  3. Add some publications (besides existing one - "Cats") in the class PubTest.
  4. Add two fields to the class Publication: purchase price and sell price. Supply appropriate methods for setting and getting their values. Test it in the program similar to PubTest demonstrating overall income of the bookshop after selling some of the publications.
  5. Create a class Employee with fields describing a person and his/her salary. Define a method for modifying salary. Test the class printing information about various employees before and after modification of their salaries.
  6. Define classes Book, Journal and CDisk, deriving from Publication. Test their functionality in some other class.

 

Lecture 8

Classes II

The previous lecture introduced the concept of a class member. We have learnt how to define classes too. However, some of the topics described there require more detailed treatment. Here we explain certain strange issues which might confuse a beginner to Java. After this lecture, the structure of a Java program should become clear to us and we'll be able to learn more about instructions, data structures or operations on strings and numbers.

 

8.1. Accessing class members. The variable this.

The time has come to discuss the class Pair in full detail.
For a while we will not bother with access modifiers (they are not important for the following example).

class Pair { int a; // class fields determine the components of objects int b; // a - the first component, b - the second component Pair(int x, int y) { // the constructor sets values of the components a = x; // based on the values supplied as arguments b = y; } Pair(int x) { // another constructor sets values of the components a = b = x; // (a and b) to the same value x } void set(Pair p) { // this method sets values of the components a = p.a; // based on components of the pair supplied as an argument b = p.b; } Pair add(Pair p) { // method for adding two pairs Pair result = new Pair(a, b); result.a += p.a; result.b += p.b; return result; } // method for printing a pair void show(String s) { System.out.println(s + " (" + a + ", " + b + ")"); } }

We can use the class Pair in another class as follows:

class PairTest { public static void main(String[] args) { Pair pair1 = new Pair(1,5); Pair pair2 = new Pair(2,4); pair1.show("Pair 1 ="); pair2.show("Pair 2 ="); Pair pairSum = pair1.add(pair2); pairSum.show("Sum of pairs ="); pair1.set(pair2); pair1.show("Pair 1 = "); } }

Pair 1 = (1, 5)
Pair 2 = (2, 4)
Sum of pairs = (3, 9)
Pair 1 = (2, 4)

The program prints:
Let us see what is going on here.

In the line:
Pair pair1 = new Pair(1, 5);
the class instance creation expression creates a new object, i.e.:


Similarly, we write:

Pair pair2 = new Pair(2,4);

Now there are two objects: pair1 and pair2.

pair1 looks like this: pair2 looks like this: Fields: Fields: int a; (= 1) int a; (= 2) int b; (= 5) int b; (= 4)---------------------------------------------Methods: Methods: void set(...) void set(...) Pair add(...) Pair add(...) void show(...) void show(...)


The identifiers of the fields and methods are the same!
Therefore they must be called for a specified object (pair1 or pair2).

The dot is used to achieve this:

pair1.a - denotes the element a from the object pair1
pair2.a - denotes the element a from the object pair2

Similarly for the methods:

pair1.show(); // the object named pair1 receives the message show
// it means invocation of the message show for the object pair1

pair2.show(); // the message show is sent to the object pair2

 

Notes:

 

Let us look inside the class. What do a and b really mean in the constructor or in the method set?
Consider the constructor:

class Pair {
int a, b;

public Pair(int x, int y) { // public is not necessary here
a = x;
b = y;
}
....
}

this is a keyword of the Java language

Inside the constructor a reference to the freshly created object is available under the (implicitly defined) variable this.
Thus, this.a and this.b - according to the meaning of the dot operator - refer to the fields a and b of this object (initialized by the constructor).

 

Because it is clear, that a and b denote fields of the object (initialized by the constructor), the word this may be skipped.

 

Similar rule holds for invocations of methods for objects.
Assume that for the object pair1 the method set with argument pair2 was called.
The method set copies values of components of the argument pair2 into the object pair1.

Here is the algorithm for set:

  1. the value of the field a of the object passed as argument is stored into the field a of the object for which the method was called
  2. the value of the field b of the object passed as argument is stored into the field b of the object for which the method was called

The object for which the method was called is represented by the keyword this inside the method.


Again, we can omit the keyword this here, as it is clear from the context.


void set(Pair p) {
a = p.a;
b = p.b;
}

In some situations the keyword this is necessary. For example, if the names of parameters are the same as the names of fields.

class Pair {
int a, b;

Pair (int a, int b) {
a =... // which a: the parameter or the field?
...
}

void set(int a, int b) {
a =... // which a: the parameter or the field?
}
}

this.a always denotes the field a of the object initialized by the constructor or the object for which the method was called. Therefore we should write:

class Pair { int a; int b; Pair(int a, int b) { this.a = a; // store the value of the parameter a into the field a this.b = b; // store the value of the parameter b into the field b } void set(int a, int b) { this.a = a; this.b = b; }}

 


Дата добавления: 2015-11-16; просмотров: 80 | Нарушение авторских прав


<== предыдущая страница | следующая страница ==>
Defining operations on objects (methods)| Static members

mybiblioteka.su - 2015-2024 год. (0.021 сек.)