181 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			181 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| ---
 | ||
| title: Constructors
 | ||
| localeTitle: Конструкторы
 | ||
| ---
 | ||
| Если объект копирует из класса, в чем смысл? Я должен иметь возможность хранить данные в нем правильно?
 | ||
| 
 | ||
| Именно тогда мы используем методы **getter** (например, getName ()) / **setter** (например, setName ()) или в этом случае конструкторы для инициализации класса. В принципе, каждый класс Java имеет конструктор, который является методом, называемым первым, когда инициализируется любой объект класса. Подумайте об этом как о стартовом коде.
 | ||
| 
 | ||
| Когда вы пишете класс без какого-либо конструктора, компилятор Java создает конструктор по умолчанию:
 | ||
| 
 | ||
| ```java
 | ||
| public class Car { 
 | ||
|     private String name; 
 | ||
|  } 
 | ||
|  
 | ||
|  Car modelS = new Car(); 
 | ||
| ```
 | ||
| 
 | ||
| Эта инициализация без параметров - способ вызова конструктора по умолчанию. Вы также можете написать конструктор по умолчанию:
 | ||
| 
 | ||
| ```java
 | ||
| public class Car { 
 | ||
|     private String name; 
 | ||
|  
 | ||
|     // User Specified Default Constructor 
 | ||
|     public Car() { 
 | ||
|         name = "Tesla"; 
 | ||
|     } 
 | ||
|  } 
 | ||
| ```
 | ||
| 
 | ||
| Затем при вызове `new Car()` `name` переменной будет автоматически инициализировано для «Tesla» для этого экземпляра объекта Car.
 | ||
| 
 | ||
| Ясно, что конструкторы в точности такие, какие они звучат: они используются для `construct` т. Е. Создают экземпляр объекта определенного класса.  
 | ||
| Конструкторы похожи на объявления методов, но немного отличаются в том смысле, что они:
 | ||
| 
 | ||
| 1.  Названы точно так же, как класс.
 | ||
| 2.  Не используйте тип возврата.
 | ||
| 
 | ||
| Следовательно, целью использования `constructors` является обеспечение:
 | ||
| 
 | ||
| 1.  Способ создания объекта.
 | ||
| 2.  Предоставить начальные значения свойствам объекта.
 | ||
| 3.  Контролируйте, как создается объект.
 | ||
| 
 | ||
| Давайте посмотрим на другой пример. Скажем, Honda (производитель автомобилей) хочет, чтобы все ее автомобили назывались `Honda <a name>` . Чтобы обеспечить это, мы можем представить это с помощью класса следующим образом:
 | ||
| 
 | ||
| ```java
 | ||
| public class Car { 
 | ||
|  
 | ||
|     private String name; 
 | ||
|  
 | ||
|     // Constructor. 
 | ||
|     public Car(String model){ 
 | ||
|         this.name = "Honda " + model; 
 | ||
|     } 
 | ||
|  
 | ||
|     public String getName(){ 
 | ||
|         return this.name; 
 | ||
|     } 
 | ||
|  
 | ||
|     public static void main(String args[]){ 
 | ||
|         Car car = new Car("Civic"); 
 | ||
|         System.out.println( car.getName() ); 
 | ||
|     } 
 | ||
|  } 
 | ||
| ```
 | ||
| 
 | ||
|  [Код запуска](https://repl.it/CTJ4/1)
 | ||
| 
 | ||
| Обратите внимание: когда мы пишем конструктор таким образом, то есть, предоставляя параметр, мы контролируем (пункт № 3) способ создания экземпляра `Car` . Короче говоря, мы говорим в этом примере, что **вы ДОЛЖНЫ предоставить имя модели, чтобы получить экземпляр класса Car** .
 | ||
| 
 | ||
| Почему это важно? Бывают случаи, когда вам нужен `one and only one` экземпляр класса для использования во всем приложении. Одним из способов достижения этого является использование `private` конструктора.
 | ||
| 
 | ||
| Предположим, вам нужен класс для представления банка. Вы бы не хотели, чтобы люди когда-либо создавали экземпляр `Bank` . Итак, вы разрабатываете свой класс:
 | ||
| 
 | ||
| ```java
 | ||
| public class Bank { 
 | ||
|  
 | ||
|     private static Bank instance; 
 | ||
|  
 | ||
|     private Bank(){ 
 | ||
|     } 
 | ||
|  
 | ||
|     public static Bank getInstance(){ 
 | ||
|         if(null == instance){ 
 | ||
|             instance = new Bank(); 
 | ||
|         } 
 | ||
|         return instance; 
 | ||
|     } 
 | ||
|  } 
 | ||
| ```
 | ||
| 
 | ||
|  [Код запуска](https://repl.it/CTJz/0)
 | ||
| 
 | ||
| Обратите внимание, что конструктор является `private` . Это подтверждает тот факт, что никто другой не может создать экземпляр Банка.  
 | ||
| На самом деле, если в другом классе вы пытаетесь:
 | ||
| 
 | ||
| ```java
 | ||
| Bank account = new Bank(); // Throws a compilation error: Bank() has private access in Bank. 
 | ||
| ```
 | ||
| 
 | ||
| Таким образом, единственный способ получить доступ к экземпляру - использовать `Bank.getInstance()` . Такие экземпляры называются `Singleton` так как вы получаете ровно один экземпляр (на каждую VM, чтобы быть точным) на протяжении всего срока действия вашего приложения.
 | ||
| 
 | ||
| В классе может быть много конструкторов. Но они должны отличаться в параметрах метода. Это перегрузка конструктора. Если быть точным, мы говорим, что перегрузка конструктора произошла, когда есть два или более конструктора с одинаковым именем, но разные параметры метода. В результате две функции имеют разные сигнатуры методов и полностью обрабатываются Java как разные конструкторы. Например:
 | ||
| 
 | ||
| ```java
 | ||
| public class Car { 
 | ||
|  
 | ||
|     private String name; 
 | ||
|     private String carType; 
 | ||
|  
 | ||
|     // Constructor. 
 | ||
|     public Car(){ 
 | ||
|         this.name = "No Name"; 
 | ||
|         this.carType = "No Type"; 
 | ||
|     } 
 | ||
|     public Car(String model){ 
 | ||
|         this.name = "Honda " + model; 
 | ||
|     } 
 | ||
|  
 | ||
|     public Car(String model, String carType){ 
 | ||
|         this.name = model; 
 | ||
|         this.carType = carType; 
 | ||
|     } 
 | ||
|  
 | ||
|     public String getName(){ 
 | ||
|         return this.name; 
 | ||
|     } 
 | ||
|  
 | ||
|     public String getCarType(){ 
 | ||
|         return this.name; 
 | ||
|     } 
 | ||
|  
 | ||
|     public static void main(String args[]){ 
 | ||
|         Car car = new Car("Civic"); 
 | ||
|         System.out.println( car.getName() ); 
 | ||
|  
 | ||
|         // Other Way To Initialize 
 | ||
|         Car car = new Car("Civic","Sedan"); 
 | ||
|         System.out.println( car.getName() + " "+ car.getCarType() ); 
 | ||
|  
 | ||
|     } 
 | ||
|  } 
 | ||
| ```
 | ||
| 
 | ||
| Таким образом, единственный способ получить доступ к экземпляру - использовать `Bank.getInstance()` . Такие экземпляры называются `Singleton` так как вы получаете ровно один экземпляр (на каждую VM, чтобы быть точным) на протяжении всего срока действия вашего приложения.
 | ||
| 
 | ||
| ## Копировать конструктор
 | ||
| 
 | ||
| Конструктор копирования - это конструктор, который создает объект, инициализируя его объектом того же класса, который был создан ранее. Конструктор копирования используется для-
 | ||
| 
 | ||
| 1.  Инициализировать объект из другого типа.
 | ||
| 2.  Скопируйте объект, чтобы передать его в качестве аргумента функции.
 | ||
| 3.  Скопируйте объект, чтобы вернуть его из функции. Вот программа, которая показывает простое использование конструктора копирования:
 | ||
| 
 | ||
| ```Java
 | ||
| class Complex { 
 | ||
|  
 | ||
|     private double re, im; 
 | ||
|  
 | ||
|     // A normal parametrized constructor 
 | ||
|     public Complex(double re, double im) { 
 | ||
|         this.re = re; 
 | ||
|         this.im = im; 
 | ||
|     } 
 | ||
|  
 | ||
|     // Copy constructor 
 | ||
|     Complex(Complex c) { 
 | ||
|         System.out.println("Copy constructor called"); 
 | ||
|         re = c.re; 
 | ||
|         im = c.im; 
 | ||
|     } 
 | ||
|  
 | ||
|     } 
 | ||
|  } 
 | ||
| ```
 | ||
| 
 | ||
| [запустить полный код](https://repl.it/MwnJ)
 | ||
| 
 | ||
| // ## Цепочка конструктора |