Руководство по созданию класс

Время на прочтение
10 мин

Количество просмотров 75K

Доброго времени суток, друзья!

В JavaScript используется модель прототипного наследования: каждый объект наследует поля (свойства) и методы объекта-прототипа.

Классов, используемых в Java или Swift в качестве шаблонов или схем для создания объектов, в JavaScript не существует. В прототипном наследовании есть только объекты.

Прототипное наследование может имитировать классическую модель наследования от классов. Для этого в ES6 было представлено ключевое слово class: синтаксический сахар для прототипного наследования.

В данной статье мы научимся работать с классами: определять классы, их частные (приватные) и открытые (публичные) поля и методы, а также создавать экземпляры.

1. Определение: ключевое слово class

Для определения класса используется ключевое слово class:

class User {
    // тело класса
}

Такой синтаксис называется объявлением класса.

Класс может не иметь названия. С помощью выражения класса можно присвоить класс переменной:

const UserClass = class {
    // тело класса
}

Классы можно экспортировать в виде модулей. Вот пример экспорта по умолчанию:

export default class User {
    // тело класса
}

А вот пример именованного экспорта:

export class User {
    // тело класса
}

Классы используются для создания экземпляров. Экземпляр — это объект, содержащий данные и логику класса.

Экземпляры создаются с помощью оператора new: instance = new Class().

Вот как создать экземпляр класса User:

const myUser = new User()

2. Инициализация: constructor()

constructor(param1, param2, …) — это специальный метод внутри класса, служащий для инициализации экземпляра. Это то место, где устанавливаются начальные значения полей экземпляра и осуществляется его настройка.

В следующем примере конструктор устанавливает начальное значение поля name:

class User {
    constructor(name) {
        this.name = name
    }
}

Конструктор принимает один параметр — name, который используется для установки начального значения поля this.name.

this в конструкторе указывает на создаваемый экземпляр.

Аргумент, используемый для создания экземпляра класса, становится параметром его конструктора:

class User {
    constructor(name) {
        name // Печорин
        this.name = name
    }
}

const user = new User('Печорин')

Параметр name внутри конструктора имеет значение ‘Печорин’.

Если не определить собственный конструктор, будет создан стандартный конструктор, представляющий собой пустую функцию, не влияющую на экземпляр.

3. Поля

Поля класса — это переменные, содержащие определенную информацию. Поля могут быть разделены на две группы:

  1. Поля экземпляров класса
  2. Поля самого класса (статические)

Поля также имеют два уровня доступа:

  1. Открытые (публичные): поля доступны как внутри класса, так и в экзмеплярах
  2. Частные (приватные): поля доступны только внутри класса

3.1. Открытые поля экземпляров класса

class User {
    constructor(name) {
        this.name = name
    }
}

Выражение this.name = name создает поле экземпляра name и присваивает ему начальное значение.

Доступ к этому полю можно получить с помощью аксессора свойства:

const user = new User('Печорин')
user.name // Печорин

В данном случае name — открытое поле, поскольку оно доступно за пределами класса User.

При неявном создании полей внутри конструктора, сложно получить список всех полей. Для этого поля нужно извлекать из конструктора.

Лучшим способом является явное определение полей класса. Неважно, что делает конструктор, экземпляр всегда имеет одинаковый набор полей.

Предложение по созданию полей класса позволяет определять поля внутри класса. Кроме того, здесь же можно присваивать полям начальные значения:

class SomeClass {
    field1
    field2 = 'Начальное значение'

    // ...
}

Изменим код класса User, определив в нем открытое поле name:

class User {
    name

    constructor(name) {
        this.name = name
    }
}

const user = new User('Печорин')
user.name // Печорин

Такие открытые поля являются очень наглядными, быстрый взгляд на класс позволяет понять структуру его данных.

Более того, поле класса может быть инициализировано в момент определения:

class User {
    name = 'Имярек'

    constructor() {
        // инициализация отсутствует
    }
}

const user = new User()
user.name // Имярек

На доступ к открытым полям и их изменение нет ограничений. Читать и присваивать значения таким полям можно в конструкторе, методах и за пределами класса.

3.2. Частные поля экземпляров класса

Инкапсуляция позволяет скрывать внутренние детали реализации класса. Тот, кто использует инкапсулированный класс, опирается на публичный интерфейс, не вдаваясь в подробности реализации класса.

Такие классы проще обновлять при изменении деталей реализации.

Хорошим способом скрыть детали является использование частных полей. Такие поля могут быть прочитаны и изменены только внутри класса, которому они принадлежат. За пределами класса частные поля недоступны.

Для того, чтобы сделать поле частным, перед его названием следует поставить символ #, например, #myPrivateField. При обращении к такому полю всегда должен использоваться указанный префикс.

Сделаем поле name частным:

class User {
    #name

    constructor(name) {
        this.#name = name
    }

    getName() {
        return this.#name
    }
}

const user = new User('Печорин')
user.getName() // Печорин
user.#name // SyntaxError

#name — частное поле. Доступ к нему можно получить только внутри класса User. Это позволяет сделать метод getName().

Однако, при попытке получить доступ к #name за пределами класса User будет выброшена синтаксическая ошибка: SyntaxError: Private field ‘#name’ must be declared in an enclosing class.

3.3. Открытые статические поля

В классе можно определить поля, принадлежащие самому классу: статические поля. Такие поля используются для создания констант, хранящих нужную классу информацию.

Для создания статических полей используется ключевое слово static перед названием поля: static myStaticField.

Добавим новое поле type для определения типа пользователя: администратора или обычного. Статические поля TYPE_ADMIN и TYPE_REGULAR — константы для каждого типа пользователей:

class User {
    static TYPE_ADMIN = 'admin'
    static TYPE_REGULAR = 'regular'

    name
    type

    constructor(name, type) {
        this.name = name
        this.type = type
    }
}

const admin = new User('Администратор сайта', User.TYPE_ADMIN)
admin.type === User.TYPE_ADMIN // true

Для доступа к статическим полям следует использовать название класса и название свойства: User.TYPE_ADMIN и User.TYPE_REGULAR.

3.4. Частные статические поля

Иногда статические поля также являются частью внутренней реализации класса. Для инкапсуляции таких полей можно сделать их частными.

Для этого следует перед названием поля поставить префикс #: static #myPrivateStaticFiled.

Предположим, что мы хотим ограничить количество экземпляров класса User. Для сокрытия информации о количестве экземпляров можно создать частные статические поля:

class User {
    static #MAX_INSTANCES = 2
    static #instances = 0

    name

    constructor(name) {
        User.#instances++
        if (User.#instances > User.#MAX_INSTANCES) {
            throw new Error('Невозможно создать экземпляр класса User')
        }
        this.name = name
    }
}

new User('Печорин')
new User('Бэла')
new User('Грушницкий') // Невозможно создать экземпляр класса User

Статическое поле User.#MAX_INSTANCES определяет допустимое количество экземпляров, а User.#instances — количество созданных экземпляров.

Эти частные статические поля доступны только внутри класса User. Ничто из внешнего мира не может повлиять на ограничения: в этом заключается одно из преимуществ инкапсуляции.

Прим. пер.: если ограничить количество экземпляров одним, получится интересная реализация шаблона проектирования «Одиночка» (Singleton).

4. Методы

Поля содержат данные. Возможность изменять данные обеспечивается специальными функциями, являющимися частью класса: методами.

JavaScript поддерживает как методы экземпляров класса, так и статические методы.

4.1. Методы экземпляров класса

Методы экземпляра класса могут изменять его данные. Методы экземпляра могут вызывать другие методы экземпляра, а также статические методы.

Например, определим метод getName(), возвращающий имя пользователя:

class User {
    name = 'Имярек'

    constructor(name) {
        this.name = name
    }

    getName() {
        return this.name
    }
}

const user = new User('Печорин')
user.getName() // Печорин

В методе класса, также как и в конструкторе, this указывает на создаваемый экземпляр. Используйте this для получения данных экземпляра: this.field, или для вызова методов: this.method().

Добавим новый метод nameContains(str), принимающий один аргумент и вызывающий другой метод:

class User {
    name

    constructor(name) {
        this.name = name
    }

    getName() {
        return this.name
    }

    nameContains(str) {
        return this.getName().includes(str)
    }
}

const user = new User('Печорин')
user.nameContains('Печорин') // true
user.nameContains('Грушницкий') // false

nameContains(str) — метод класса User, принимающий один аргумент. Он вызывает другой метод экземпляра getName() для получения имени пользователя.

Метод также может быть частным. Для того, чтобы сделать метод частным следует использовать префикс #.

Сделаем метод getName() частным:

class User {
    #name

    constructor(name) {
        this.#name = name
    }

    #getName() {
        return this.#name
    }

    nameContains(str) {
        return this.#getName().includes(str)
    }
}

const user = new User('Печорин')
user.nameContains('Печорин') // true
user.nameContains('Грушницкий') // false

user.#getName // SyntaxError

#getName() — частный метод. Внутри метода nameContains(str) мы вызываем его так: this.#getName().

Будучи частным, метод #getName() не может быть вызван за пределами класса User.

4.2. Геттеры и сеттеры

Геттеры и сеттеры — это аксессоры или вычисляемые свойства. Это методы, имитирующие поля, но позволяющие читать и записывать данные.

Геттеры используются для получения данных, сеттеры — для их изменения.

Для установки запрета на присвоение полю name пустой строки, обернем частное поле #nameValue в геттер и сеттер:

class User {
    #nameValue

    constructor(name) {
        this.name = name
    }

    get name() {
        return this.#nameValue
    }

    set name(name) {
        if (name === '') {
            throw new Error('Имя пользователя не может быть пустым')
        }
        this.#nameValue = name
    }
}

const user = new User('Печорин')
user.name // вызывается геттер, Печорин
user.name = 'Бэла' // вызывается сеттер

user.name = '' // Имя пользователя не может быть пустым

4.3. Статические методы

Статические методы — это функции, принадлежащие самому классу. Они определяют логику класса, а не его экземпляров.

Для создания статического метода используется ключевое слово static перед названием метода: static myStaticMethod().

При работе со статическими методами, следует помнить о двух простых правилах:

  1. Статический метод имеет доступ к статическим полям
  2. Он не имеет доступа к полям экземпляров

Создадим статический метод для проверки того, что пользователь с указанным именем уже создан:

class User {
    static #takenNames = []

    static isNameTaken(name) {
        return User.#takenNames.includes(name)
    }

    name = 'Имярек'

    constructor(name) {
        this.name = name
        User.#takenNames.push(name)
    }
}

const user = new User('Печорин')

User.isNameTaken('Печорин') // true
User.isNameTaken('Грушницкий') // false

isNameTaken() — статический метод, использующий частное статическое поле User.#takenNames для определения использованных имен.

Статические методы также могут быть частными: static #myPrivateStaticMethod(). Такие методы могут вызываться только внутри класса.

5. Наследование: extends

Классы в JavaScript поддерживают наследование с помощью ключевого слова extends.

В выражении class Child extends Parent { } класс Child наследует от класса Parent конструктор, поля и методы.

Создадим дочерний класс ContentWriter, расширяющий родительский класс User:

class User {
    name

    constructor(name) {
        this.name = name
    }

    getName() {
        return this.name
    }
}

class ContentWriter extends User {
    posts = []
}

const writer = new ContentWriter('Лермонтов')

writer.name // Лермонтов
writer.getName() // Лермонтов
writer.posts // []

ContentWriter наследует от User конструктор, метод getName() и поле name. В самом ContentWriter определяется новое поле posts.

Обратите внимание, что частные поля и методы родительского класса не наследуются дочерними классами.

5.1. Родительский конструктор: super() в constructor()

Для того, чтобы вызвать конструктор родительского класса в дочернем классе, следует использовать специальную функцию super(), доступную в конструкторе дочернего класса.

Пусть конструктор ContentWriter вызывает родительский конструктор и инициализирует поле posts:

class User {
    name

    constructor(name) {
        this.name = name
    }

    getName() {
        return this.name
    }
}

class ContentWriter extends User {
    posts = []

    constructor(name, posts) {
        super(name)
        this.posts = posts
    }
}

const writer = new ContentWriter('Лермонтов', ['Герой нашего времени'])
writer.name // Лермонтов
writer.posts // ['Герой нашего времени']

super(name) в дочернем классе ContentWriter вызывает конструктор родительского класса User.

Обратите внимание, что в дочернем конструкторе перед использованием ключевого слова this вызывается super(). Вызов super() «привязывает» родительский конструктор к экземпляру.

class Child extends Parent {
    constructor(value1, value2) {
        // не работает!
        this.prop2 = value2
        super(value1)
    }
}

5.2. Родительский экземпляр: super в методах

Для того, чтобы получить доступ к родительскому методу внутри дочернего класса, следует использовать специальное сокращение super:

class User {
    name

    constructor(name) {
        this.name = name
    }

    getName() {
        return this.name
    }
}

class ContentWriter extends User {
    posts = []

    constructor(name, posts) {
        super(name)
        this.posts = posts
    }

    getName() {
        const name = super.getName()
        if (name === '') {
            return 'Имярек'
        }
        return name
    }
}

const writer = new ContentWriter('', ['Герой нашего времени'])
writer.getName() // Имярек

getName() дочернего класса ContentWriter вызывает метод getName() родительского класса User.

Это называется переопределением метода.

Обратите внимание, что super можно использовать и для статических методов родительского класса.

6. Проверка типа объекта: instanceof

Выражение object instanceof Class определяет, является ли объект экземпляром указанного класса.

Рассмотрим пример:

class User {
    name

    constructor(name) {
        this.name = name
    }

    getName() {
        return this.name
    }
}

const user = new User('Печорин')
const obj = {}

user instanceof User // true
obj instanceof User // false

Оператор instanceof полиморфичен: он исследует всю цепочку классов.

class User {
    name

    constructor(name) {
        this.name = name
    }

    getName() {
        return this.name
    }
}

class ContentWriter extends User {
    posts = []

    constructor(name, posts) {
        super(name)
        this.posts = posts
    }
}

const writer = new ContentWriter('Лермонтов', ['Герой нашего времени'])

writer instanceof ContentWriter // true
writer instanceof User // true

Что если нам нужно определить конкретный класс экземпляра? Для этого можно использовать свойство constructor:

writer.constructor === ContentWriter // true
writer.constructor === User // false
// или
writer.__proto__ === ContentWriter.prototype // true
writer.__proto__ === User.prototype // false

7. Классы и прототипы

Надо сказать, что синтаксис классов — это хорошая абстракция над прототипным наследованием. Для использования классов не нужно обращаться к прототипам.

Однако, классы являются лишь надстройкой над прототипным наследованием. Любой класс — это функция, создающая экземпляр при вызове конструктора.

Следущие два примера идентичны.

Классы:

class User {
    constructor(name) {
        this.name = name
    }

    getName() {
        return this.name
    }
}

const user = new User('Печорин')

user.getName() // Печорин
user instanceof User // true

Прототипы:

function User(name) {
    this.name = name
}

User.prototype.getName = function () {
    return this.name
}

const user = new User('Печорин')

user.getName() // Печорин
user instanceof User // true

Поэтому для понимания классов требуется хорошее знание прототипного наследования.

8. Доступность возможностей классов

Возможности классов, представленные в данной статье, распределены между спецификацией ES6 и предложениями, находящимися на третьей стадии рассмотрения:

  • Открытые и частные поля экземпляров
  • Частные методы экземпляров и аксессоры
  • Открытые и частные статические поля и частные статические методы
  • Спецификация ES6

Прим. пер.: по данным Can I use поддержка частных полей классов на сегодняшний день составляет 68%.

9. Заключение

Классы в JavaScript используются для инициализации экземпляров с помощью конструктора, определения их полей и методов. С помощью ключевого слова static можно определять поля и методы самого класса.

Наследование реализуется с помощью ключевого слова extends. Ключевое слово super позволяет получить доступ к родительскому классу из дочернего.

Для того, чтобы воспользоваться преимуществами инкапсуляции, т.е. скрыть внутренние детали реализации, сделайте поля и методы частными. Названия таких полей и методов должны начинаться с символа #.

В современном JavaScript классы используются повсеместно.

Надеюсь, статья была вам полезной. Благодарю за внимание.

Вы новичок в Google Class и хотите узнать, как его создать, или хотите узнать больше о создании контента в Google Classes? Тогда эта статья для вас. Мы собрали полное руководство о процессе создания полного класса Google, где вы можете взаимодействовать со своими учениками в качестве учителя или где вы можете взаимодействовать со своими однокурсниками в качестве ученика.

В этой статье вы также узнаете, как создать класс Google, давать своим ученикам задания и без проблем оценивать их соответственно. Все, что вам нужно сделать, это прочитать эту статью до конца.

Мы предполагаем, что когда будущие историки будут изучать эволюцию классной комнаты, они увидят появление Google Classroom как решающий поворотный момент. В конце концов, мы не можем отрицать, что Google стал великим предвестником перемен в современном мире, особенно в том, как мы общаемся и работаем.

Поэтому неудивительно, что Google также меняет то, как мы преподаем и учимся. Итак, мы все согласны с тем, что, несмотря на изобретательность и удобство, Google Classroom был неизбежен. Когда вы здесь, вы увидите ценность участия в классе Google.

How to Create a Google Classroom

Как создать класс Google

Google Classroom, основанный на принципе продуктивности, представляет собой практичный и оптимизированный инструмент, который учителя могут создавать и использовать для управления своими занятиями. уроки в одном месте. Учителя могут создавать классы, назначать домашние задания, оценивать и комментировать домашние задания, а также легко настраивать и управлять своим учебным процессом.

Думайте о Google Classroom как о полезном ресурсе, а не как об учебной среде с полным спектром услуг, такой как Seesaw или Edpuzzle.

Читайте также:15 идей Google Meet для учителей

Как я могу получить доступ к Google Classroom?

Независимо от того, являетесь ли вы учителем государственной школы или частным учителем, у вас должна быть учетная запись Google для доступа к Google Classroom на вашем ноутбуке / рабочем столе из браузера. Пока вы используете G-Suite for Education или у вас есть личная учетная запись Google, все в порядке. Вы также можете загрузить приложение Google Classroom для своего устройства Android или iOS, чтобы управлять своими занятиями с других устройств.

Как создать класс в Google Classroom

Чтобы создать Google Classroom, вам сначала нужно создать учетную запись Google Classroom. Вот как это сделать.

Как войти в Google Класс

Чтобы войти в Класс, перейдите на Класс.google.com. Если вы уже вошли в свою учетную запись Google, вы сразу попадете на страницу Класса.

How to Create a Google Classroom

Как создать класс Google

Если вы не видите эту страницу, значит, вы были перенаправлены на эту страницу с edu.google.com. Не волнуйтесь, просто нажмите Перейти в класс отсюда.

How to Create a Google Classroom

Теперь вам будет предложено войти в свою учетную запись Google.

How to Create a Google Classroom

После входа вы увидите ту же страницу Google Classroom, что и выше.

Превосходно! Теперь, когда вы внутри, вы готовы создать класс Google в классе Google.

Читайте также: Как использовать Google Meet в Google Classroom

Как создать класс

Вы общаетесь напрямую со своими учениками в классе. После того, как вы изучите механику, вы сможете создавать разные классы в зависимости от вашего уровня и раздела. Мы покажем вам, как создать класс, и вы можете использовать тот же учебник, чтобы сделать больше.

Вы увидите еще один значок в правом верхнем углу экрана. Вы должны нажимать на этот символ каждый раз, когда хотите создать новый класс Google. Он всегда есть на странице вашего класса. Возможно, Google уже создал сообщение, побуждающее вас щелкнуть значок. Однако, если вы его не видите, значок выглядит так.

How to Create a Google Classroom

Теперь щелкните значок и выберите «Создать класс».

How to Create a Google Classroom

Теперь, если вы используете личную учетную запись Google вместо учетной записи G-Suite вашей школы, вы увидите этот отказ от ответственности. Пожалуйста, примите его и нажмите «Далее».

Теперь мы находимся в реальной части, где вы создадите Google Classroom. Введите сведения о классе, включая название (обязательно), раздел, тему и номер класса (необязательно). Когда вы введете данные, нажмите «Создать».

How to Create a Google Classroom

Совет. Хотя раздел, тему и номер комнаты указывать необязательно, их можно настроить в соответствии со своими потребностями. Например, этот раздел может быть полезен для ввода краткого описания вашего класса, уровня обучения или времени урока. Вы также можете описать свою тему или выбрать из списка, предоставленного Google.

Превосходно! Вы создали свой первый курс Google. Когда вы выполните все шаги, вы увидите страницу своего класса.

Читайте также: Как исправить проблему с потоком Google Classroom исчезла

Установите тему для своего класса Google

Создав свой класс Google, вы можете определить для него тему. В углу обложки вы увидите две опции: выбрать тему и загрузить фотографии.

Если вы хотите создать обложку или уже создали ее, нажмите «Загрузить фото». Теперь вам будет предложено выбрать изображение с вашего компьютера.

Выберите изображение и загрузите его. После того, как вы это сделаете, вам нужно будет выбрать и вырезать определенную часть в зависимости от размеров фотографии обложки. Если вы не хотите обрезать изображение, сделайте его размером 1000 x 250 пикселей, чтобы обрезка не требовалась. Когда вы закончите, нажмите выбрать тему класса.

Или… вы можете выбрать архивную тему, которая уже доступна. Для этого нажмите кнопку Выбрать тему. Щелкните тему, которая вам нравится, затем выберите тему курса.

Теперь, когда вы довольны тем, как выглядит ваш класс, пришло время добавить учеников.

Вот как добавить учащихся в ваш класс Google

До сих пор вы просматривали раздел потока в своем Google Classroom. Пришло время переключиться на другую вкладку. В верхней части экрана есть четыре вкладки: «Поток», «Задания», «Люди» и «Отметки». Откройте вкладку Люди.

На странице «Люди» вы увидите два раздела: приглашение других преподавателей и приглашение студентов. В разделе «Студент» вы увидите значок профиля; нажмите здесь.

How to Create a Google Classroom

Окно попросит вас добавить студентов. Введите их учетные данные электронной почты в поле получателя и нажмите Пригласить.

Если вы хотите пропустить процесс приглашения и иметь другое средство связи, вы также можете использовать код класса. Скопируйте его с вкладки «Поток» и поделитесь им напрямую.

How to Create a Google Classroom

Здесь! Теперь учащиеся могут присоединиться к вашему классу и пройти курсы. Теперь вы можете начать назначать задания своим учащимся и добавлять контент в ленту своего класса, на который ваши учащиеся могут ссылаться.

Читайте также: Как получить Bitmoji в Google Classroom

Как создать контент для своего потока в Google Classroom

Вкладка «Задания» используется для создания контента. Создание контента на сайте Classwork состоит из трех основных частей: «Создание», «Календарь Google» и «Папка Class Drive».

How to Create a Google Classroom

Создавай

Кнопка «Создать» дает вам форматы, с помощью которых вы можете настроить свой контент в классе Google.

How to Create a Google Classroom

Назначение

Параметр «Домашнее задание» позволяет вам назначать общие упражнения для вашего класса. Почти все, что можно настроить на Google Диске с помощью документов, слайдов, электронных таблиц и т. д., можно указать в формате карты.

How to Create a Google Classroom

В правой части страницы создания задания вы можете установить дату выполнения, систему оценивания и выбрать группу учащихся, которой вы хотите назначить задание.

How to Create a Google Classroom

Когда все будет в порядке, нажмите Назначить. Это показано в правом верхнем углу страницы.

click on assign

Задание викторины

Для заданий викторины Google предоставляет специальную форму викторины Google для создания викторин и вопросов с несколькими вариантами ответов. Это также упрощает вашу жизнь, так как Google будет вести журнал всех ответов, и вы сможете легко оценить их.

Как и в случае с назначением, назначьте дату выполнения и другие детали, прежде чем нажимать кнопку «Назначить».

Вопрос

Теперь представьте ситуацию в реальном классе, где вы задаете ученикам вопрос, чтобы начать обсуждение. Вопрос в цифровом эквиваленте чего-то подобного. Создав вопрос, вы можете открыть его, чтобы класс мог прокомментировать его и начать обсуждение.

Материалы

Довольно легко заметить. Материал — это категория конспектов лекций или материалов, которыми вы хотите поделиться со своими студентами.

How to Create a Google Classroom

Как создать класс Google

Для всех действий, связанных с выставлением оценок, Google Classroom добавляет вкладку «Работы учащихся» рядом с основным заданием. В этом разделе вы можете проверить, отправил ли студент свою работу или нет.

How to Create a Google Classroom

Повторно использовать пост

Конечно, для созданияотлично В классе Google вам нужно использовать сохраненные форматы, вам будет сложно создавать задачи с нуля, особенно если у вас фиксированный формат. Здесь в игру вступает функция повторного использования. Просто нажмите на задачу, которую вы хотите реплицировать, а затем нажмите «Повторно использовать».

Затем вы можете отредактировать и сбросить содержимое задания, чтобы получить доступ к потоку Google Classroom, когда вы нажимаете на публикацию.

Папка на Диске Класса

Google автоматически отображает весь контент, который вы создаете и сохраняете для курса, в папке, относящейся к этому курсу. Ваши ученики также будут иметь доступ к этой папке.

Google Calendar

Календарь Google хранит вкладку со сроками выполнения всех назначенных вами заданий. Вы также будете уведомлены календарем, когда крайний срок закрыт или истек. Вот как ваша домашняя работа отображается в календаре.

Рекомендации:

  • 10 лучших научных конкурсов 2020 г.
  • Отрицательное влияние онлайн-игр на учащихся
  • Список глобальных конкурсов для студентов 2020 г.
  • Поступление в университеты США для иностранных студентов
  • Отрицательное влияние онлайн-игр на учащихся

#статьи


  • 0

ООП — это то, на чём держится вся разработка на Java. С помощью объектов и классов можно создать любой функционал быстрее.

 vlada_maestro / shutterstock

Евгений Кучерявый

Пишет о программировании, в свободное время создаёт игры. Мечтает открыть свою студию и выпускать ламповые RPG.

Объектно-ориентированное программирование — это подход к разработке приложений с помощью классов и объектов. Он позволяет писать значительно меньше кода и при этом реализовывать больше возможностей, чем при функциональном проектировании программ.

В программе, написанной по принципам ООП, отдельные компоненты рассматриваются как предметы из реального мира, такие как дом, дерево, кот, человек и даже Java-разработчик. У каждого объекта есть свои атрибуты. Вот какими они будут у принтера: цвет, марка, скорость печати, объём оставшейся краски и так далее.

Также принтеру свойственно определённое «поведение»: печать, сканирование, копирование, проверка наличия краски, подключение к Wi-Fi и так далее — всё это называется методами.

Каждый принтер уникален, поэтому обладает своим идентификатором, по которому к нему можно обратиться, чтобы узнать или изменить тот или иной атрибут, а также вызвать метод:

Объект.метод()
Объект.атрибут = значение;

Однако прописывать все атрибуты и методы для каждого объекта было бы слишком сложно, поэтому используются классы — общий шаблон того, как должен вести себя объект.

Допустим, существует класс Бумага, которому прописываются свои параметры и методы: цвет, цена, размер, толщина и так далее. Каждый отдельный объект является экземпляром класса. Например, можно создать объект листБумаги1, листБумаги2, листБумаги3 — у всех них будут одинаковые атрибуты и поведение, но разные значения:

листБумаги1.размер = А4; листБумаги1.цена = 2;
 листБумаги2.размер = А5; листБумаги2.цвет = серый;

Эту бумагу можно, например, передать объекту класса Принтер, чтобы её распечатать:

принтерВОфисе.печать(текст, листБумаги1); 

Без объектов нам бы пришлось создавать отдельные функции и работать с ними. Сейчас мы можем написать такой код:

Принтер принтерВОфисе = новый Принтер(127.0.0.1, А4);
Бумага листБумаги1 = новая Бумага(А4);

Строка текст = «Привет, мир!»;
ПринтерВОфисе.печать(текст, листБумаги1);

То есть мы создаём объект и даём ему параметры: адрес и размер. Потом отправляем ему текст и лист бумаги, а он печатает это так, как прописано в теле метода.

Без классов нам бы пришлось создавать множество негруппированных переменных, в которых хранилась бы вся эта информация:

Строка адресПринтераВОфисе = 127.0.0.1;
Число размерПринтераВОфисе = А4;

Число размерЛиста1 = А4;

напечататьТекст(текст, адресПринтераВОфисе, размерПринтераВОфисе, размерЛиста1) {
	если (размерЛиста1 == размерПринтераВОфисе) {
		отправитьТекст(текст, адресПринтераВОфисе); 
}
}

Представьте, как раздуется код от количества переменных и функций, которые нужны, чтобы распечатать обычный лист. А ведь нужно написать ещё и функцию заправки, сканирования, копирования и так далее.

Пришлось бы несколько раз дублировать одинаковые фрагменты кода, чтобы написать что-то. А ООП позволяет сократить код, а значит, быстрее разрабатывать программы, а также читать и переписывать их.

Создавая программу, нужно объявить класс с её именем, а потом добавить метод main — из него начинается работа приложения:

public class ClassesProgram {
	public static void main(String[] arg) {		
		System.out.println("Hello, World!");
	}
}

В Java всё, что не является объектом, является классом. Даже System, с помощью которого выводится текст, — это объект.

Можно создать переменные для этого класса — атрибуты:

public class ClassesProgram {
	public static int num1 = 25;
	public static int num2 = 2;
	
	public static void main(String[] arg) {
		int sum = num1 * num2;
		System.out.println("sum: " + sum);
	}
}

Эти переменные вызываются из основного метода и умножаются. Вот как выглядит результат таких вычислений:

Пока не обращайте внимания на слова public и static — про них мы расскажем позже. Так же можно создавать методы, похожие на main. Для них укажите модификаторы доступа (public и static), возвращаемый тип и название:

public class ClassesProgram {
	
	public static int GetCube(int x) {
		return x * x * x;
	}
	
	public static void main(String[] arg) {		
		int cube = GetCube(5);
		
		System.out.println("Cube: " + cube);		
	}
}

Запустив программу, мы увидим результат работы метода GetCube ():

Пока всё работает в пределах основного класса, но можно создать и другие. Для наглядности мы будем делать это на примере кода мессенджера. Здесь будут использоваться классы Сообщение (Message) и Пользователь (User).

Чтобы начать работать с классами, создайте папку для своего проекта: например, 01. Добавьте в неё ещё два каталога — src и bin. В первом будут храниться исходники, а во втором — скомпилированные файлы.

Теперь скомпилировать файл можно так:

javac -d bin src/ClassesProgram.java

А запустить — так:

java -cp ./bin ClassesProgram

Все классы должны находиться в отдельных файлах. которые нужно объединить в пакет. Его название должно выглядеть так: com.sitename.packagename. Хотя вы можете обойтись и без домена packagename. Чтобы создать пакет, сначала в папке src создайте следующую структуру:

src\packagename\component\file.java

В нашем случае для основного файла путь будет таким:

src\mypackege\classesprogram\ClassesProgram.java

В тот же каталог поместите User.java и Message.java. После этого в начало каждого файла добавьте такую строчку:

package mypackage.classesprogram;

Она означает, что этот код относится к определённому пакету. И чтобы воспользоваться каким-то классом, нужно добавить в начало основной программы несколько команд:

import mypackage.classesprogram.User;
import mypackage.classesprogram.Message;

Теперь можно компилировать программу с помощью команды:

javac -sourcepath ./src -d bin src/mypackage/classesprogram/ClassesProgram.java

Если вы всё сделали правильно, в папке bin появится такая же структура, как в src. Вот код корневого файла приложения:

package mypackage.classesprogram; //Добавляем файл в пакет

//Подключаем отдельные классы
import mypackage.classesprogram.User;
import mypackage.classesprogram.Message;

//Подключаем пакет для работы с пользовательским вводом
import java.util.Scanner;


public class ClassesProgram {
	
	public static void main(String[] arg) {
		Scanner in = new Scanner(System.in);
		
		System.out.println("Success!");

	}
}

Теперь этот код можно запустить, прописав такую команду:

java -classpath ./bin mypackage.classesprogram.ClassesProgram

Вот что выведет консоль:

Этот процесс можно ускорить, если скачать IDE. Там для добавления нового класса достаточно будет выполнить несколько действий в графическом интерфейсе. Например, в Eclipse можно нажать File -> new -> class — этого будет достаточно.

Но если вы пока не уверены, что хотите продолжать работать на Java, можете поэкспериментировать в консоли.

Теперь можно приступить к созданию классов. Начнём с пользователя:

package mypackage.classesprogram;

public class User {
	public String name;
	public int age; 
}

Слово public выступает модификатором доступа — он определяет, откуда будет доступен компонент. Для класса можно указать следующие модификаторы:

  • public — доступно в любых частях программы (применимо и к другим компонентам);
  • default — доступно только классам из того же пакета.

Теперь в основном файле можно создать объект класса User:

Scanner in = new Scanner(System.in);

User user1 = new User();
System.out.println("Enter your name: ");
user1.name = in.nextLine();

System.out.println("Enter your age: ");
user1.age = in.nextInt();

System.out.println(user1.name + " is " + user1.age + " years old!");

Мы указали для объекта user1 класс User, а после оператора присваивания указали ключевое слово new и запустили конструктор (об этом позже). Вот как будет выполнена программа:

Создание объекта называется объявлением экземпляра класса — тут же можно использовать конструктор, чтобы сразу задать значения атрибутам.

Для этого нужно в теле класса создать метод с таким же названием, что и класс. Ему можно передать аргументы, с которыми можно провести операции:

public class User {
	public String name;
	public int age; 
	
	public User(String name, int age) {
		this.name = name;
		this.age = age;
		
		System.out.println("User " + this.name + " was created. His (her) age is " + this.age);
	}
}

Обратите внимание, что внутри класса атрибуты вызываются с помощью ключевого слова this. Это нужно для того, чтобы компилятор не путался, с какой переменной работать — например, в случае, если у аргумента такое же имя, как и у атрибута:

Теперь, чтобы создать объект, нужно немного поменять код:

System.out.println("Enter your name: ");
String name = in.nextLine();

System.out.println("Enter your age: ");
int age = in.nextInt();

User user1 = new User(name, age);

Дальше можно создать класс для работы с сообщениями:

package mypackage.classesprogram;
import mypackage.classesprogram.User;

public class Message {
	private String text;
	private User from;
	private User to;
	
	public Message(String text, User from, User to) {
		this.text = text;
		this.from = from;
		this.to = to;
		
		System.out.println(this.from.name + " wrote to " + this.to.name + ": " + this.text);
	}
}

Обратите внимание, что в этот раз для атрибутов from и to мы задали модификатор private, а в качестве типа стоит User. Private позволяет закрыть доступ к элементам извне — то есть их можно менять только внутри методов самого класса.

Это позволяет защитить атрибуты от незапланированного доступа. Если же вы хотите получать или менять атрибуты, можно воспользоваться getter и setter. Это специальные методы, которые позволяют обратиться к защищённой переменной:

public String getText() {
	return this.text;
}

public void setTo(User to) {
	this.to = to;
}

Теперь можно написать код, который будет создавать сообщение:

System.out.println("Enter your name: ");
String name = in.nextLine();

System.out.println("Enter your age: ");
int age = in.nextInt();

User user1 = new User(name, age);
User user2 = new User("John", 20);

System.out.println("Enter your message: ");
String text = in.nextLine();

Message msg = new Message(text, user1, user2);	

Вот как это работает:

Так с помощью классов и объектов можно быстро создать какую-нибудь программу, используя минимум кода. Можно также добавить класс Chat, в котором будут храниться все сообщения от одного пользователя к другому — для этого нужно освоить не только классы, но и коллекции.

Это лишь малая часть того, как происходит работа с объектами и классами. Существуют ещё такие понятия, как наследование, полиморфизм, инкапсуляция и многое другое.

Как зарабатывать больше с помощью нейросетей?
Бесплатный вебинар: 15 экспертов, 7 топ-нейросетей. Научитесь использовать ИИ в своей работе и увеличьте доход.

Узнать больше

Introduction

Java class is the basic building block of Java programming language. Java class is a template used to create objects and to define data types and methods.Java class objects should have the basic class properties. This article will explain how Java classes work with code examples.

What are Java Classes?

Java class is the basic concept of object-oriented programming language. Java class is a user-defined template or blueprint where objects, data members, and methods are defined and a set of instructions to build a specific object type. The variables and methods of the same Java class are common for all the class objects.

In Java, the class keyword is used to define a Java class.

How is a Java Class defined?

Syntax

class <class-name>

{

         [data members]

         [method];

}

Code Example

class MyClass   
{  
       int x = 5;         //data member;   
       void fun()  //
       {  
              System.out.println("This is method");  
       }     
}  

What are the three major components of the Java class?

1) What are the class variables in Java?

A variable is a reserved memory location to hold a value. In other words, when we want to store any value and give it a name, that value takes a reserved space in memory, and it’s called a variable.

A variable has any value which is located in the memory.

Syntax

<access specifier > < data type > < variable name > = < value > ;

How can we declare the Variable?

Code Example

int x ;     (int is a data type and x is a variable name).  
int y;  
int x , y;  
int x = 4 , y = 5;  
byte p = 65;  
double pi = 3.1415;  
char q = ‘s’ ; 

What are the different types of Variables in Java?

1. Local Variable in Java

A variable declared inside any methods, constructors, and blocks is known as a local variable. It is created after the creation of the method, constructor, block, and a local variable is not visible to the class and not accessed by the class. Its scope is limited because it is used locally in the method.

For example, first, we create a class and a method. Afterward, declare two local variables inside the method.

Code Example

public class LocalVariableExm {  
    void message() {     //it is a method.  
        int p;                     // declaration of Local Variable.  
        int x = 10;      // declaration and initialization of Local Variable.  
    }  
} 

Static Variable in Java

A static variable is a very important type of Variable. We use static keywords with the Variable. Hence, it’s called a static variable. Static Variable is declared inside the class and outside the method, constructor, and block. The static variable belongs to the class, not an Object, and is stored in static memory. Its default value is 0, which we can call the static Variable with its class name. Hence, creating an object in a static variable is unnecessary.

For example, first, we create a class and three variables outside the method, where two variables are static variables.

Code Example

public class StaticVariableExm {  
    int p;  
    static int q = 10;     // Static Variable with initialization  
    static int r;              // Static Variable declaration  
    void message() {  
    }  
} 

Instance Variable in Java 

An instance variable is declared inside the class but outside the method, constructor, or block. It has the most comprehensive scope because it is globally visible to the class. It is created at the time of object creation. When the instance variable is created at that time, it takes space in the heap memory, and is called through the object, and the default value is 0.

For example, first, we create a class and two instance variables outside the method.

Code Example

public class InstanceVariableExm {  
    int a;      // Declaration of instance variable.  
    int b = 10;  // Declaration and initialization of instance variable.  
    void message() {  
    }  
} 

2) What is Constructor in Java?

A constructor is like a special method in Java, which is used to initialize an object of a Java class Constructor is very important for every Java class. If we don’t declare the constructor, the compiler creates a default constructor of a Java class.

A constructor must be the same name as a Java class. It does not have a return type.

What are the different types of constructors in Java?

In Java, Constructors can be divided into three types.

Default constructor in Java

The default constructor has no parameter, and if we do not declare a constructor, the compiler automatically creates a default constructor of that Java class.

Syntax

<class-name>() {   } 

In the following program, we create a default constructor and print a message as an output. The complete program is listed below.

public class DefaultConstructor{    
    DefaultConstructor() {  
        System.out.println("This is default constructor example");  
    }    
    public static void main(String args[]) {  
        DefaultConstructor d = new DefaultConstructor();  
    }  
}  

The output of the above code generates the following output.

The default constructor provides the default value to the object, like 0 or null. The value depends on their type.

In the following program, we are not creating a constructor compiler to provide it by default and provide default values. The complete program is listed below.

public class DefaultConstructor2 {  
    String name;  
    String number;    
    void display() {  
        System.out.println(name + "," + number);  
    }    
    public static void main(String args[]) {  
        DefaultConstructor2 t = new DefaultConstructor2();  
        t.display();  
    }  
} 

The output of the following code generates the following output.

 

Parameterized constructor  in Java

A constructor that has parameters is called a parameterized constructor in Java. We use the parameterized constructor to provide different values to distinct objects.

In the following program, we create a parameterized constructor with two parameters. The complete program is listed below. 

public class ParameterizedConstructor {   
    String name;  
    int salary;    
    ParameterizedConstructor(String n, int s) {  
        name = n;  
        salary = s;  
    }    
    void display() {  
        System.out.println("Employee name is: " + name + "," + "and salary is : " + salary);  
    }    
    public static void main(String args[]) {  
        ParameterizedConstructor e = new ParameterizedConstructor("Rohan", 25000);  
        e.display();  
    }  
} 

The output of the following code generates the following output.

 

Copy constructor in Java.

Copy constructor in Java class is a special constructor that takes the same class as an argument. A copy constructor is used to provide a copy of the specified object.

A copy constructor is used when we want to copy an object that is heavy to initiate. The complete program is listed below.

public class CopyConstructor {    
    int empid;  
    public CopyConstructor(int b) {  
        empid = b;  
    }    
    public void disp() {  
        System.out.println("Employee id is :" + empid);  
    }    
    public static void main(String[] args) {  
        CopyConstructor e = new CopyConstructor(1002);  
        e.disp();  
    }  
} 

The output of the following code generates the following output.

 

3) What are the methods in the Java class?

Methods are used to perform certain actions, also known as functions. A method is a block of code that only runs when called. You can pass data, known as parameters, into a method.

Why do we use Methods in Java Classes?

To reuse code: define it once and use it many times.

How to create a method in the Java class?

A method must be declared within a class. It is defined with the method’s name, followed by parentheses ().

Syntax

 class <class-name> {

    modifier dataType methodName () {

         //block of code to be executed     } }

//calling the method from anywhere

className.methodName();

The complete program is listed below.

public class MethodExample {    
    static void myMethod() {  
        System.out.println("Hello World!");  
    }    
    public static void main(String[] args) {  
        myMethod();  
    }  
} 

The output of the following code generates the following output.

Methods with parameters in Java

A parameter is a value you can pass to a method in Java. Then the method can use the parameter as though it were a local variable initialized with the Variable’s value passed to it by the calling method.

Types of Parameters in Java 

Formal Parameter: A variable and its type as they appear in the prototype of the function or method.

Syntax

function_name(datatype variable_name)

Actual Parameter: The Variable or expression corresponding to a formal parameter that appears in the function or method call in the calling environment.

Syntax

func_nme(variable name(s));

The complete program is listed below.

public class ParameterizedMethodExample {    
    static void myMethod(String name) {  
        System.out.println(name);   
    }    
    public static void main(String[] args) {  
        myMethod("CsharpCorner");  
    }  
} 

The output of the following code generates the following output.

Note. Java class declaration can contain objects, class members, access modifiers, and constructors.

What are Objects in Java class?

An object is a fundamental concept of oops like java classes .objects are like an entity with a state and behavior. Like cars, mobiles, pencils, cats, etc. A car has states(its color, name, and brand) and behavior(running). Objects are instances of a java class, and objects can be tangible and intangible. Objects represent identity, which uniquely identifies it. One car number plate is a different number of other cars. So, it is the car’s identity that is unique.

Objects represent the value of an object, like car name, color, and brand. Objects represent the functionality of an object, like a car’s functionality running.

How to create an object in Java class?

In Java new keyword is used to create an object.

Syntax

<class-name> [object-name] = new <class-default-conetructor>

Example Code  

class ObjectCreationExample   
{           
    public static void main(String args[]) {    
  
        ObjectCreationExample s = new ObjectCreationExample();   // create an object.    
    }   
}  

What are Data Members in Java class?

Data members are those whose memory space is created every time whenever an object is created. Data members are always meant to store a specific value.

Syntax

Data type v1,v2,v3,……..vn;

class DataMember  
{  
   int v1,v2,v3;  
   float f1,f2;    
}  

What are Access Modifiers in Java class?

The access Modifiers give the accessibility (scope) of a java class, data member, method, or constructor. Access Modifiers help us set the access level for our java class, variables, and methods.

What are the different types of access modifiers?

There are four types of Java access modifiers.

  1. public 
  2. private
  3. protected
  4. default

Modifiers Accessability

The following table lists access modifiers.

 Access Modifiers  Keywords
 Public access modifier   public
 Private   private 
 Protected   protected
 Default  no keyword used

1) Public Access Modifier.

The public access modifier is accessible in all places. It has the most comprehensive scope among all other modifiers. Variables, methods, and constructors are declared public within a public class visible to any class in the java program. Hence, it doesn’t matter whether these classes are in the same package or another package.

The complete program is listed below.

Step 1. First, we create a Java class PublicExample in which we declare the method show():

public class PublicExample {      
    public void show() {    
        System.out.println("Public access modifier example");   
    }    
}  

Step 2. Second, we create a class called PublicAccess which we call the method of PublicExample class.

public class PublicAccess {    
        public static void main(String args[])    
        {  
            PublicExample obj = new PublicExample();    
            obj.show();    
        }  
    }  

The output of the following code generates the following output.

 

2) Private Access Modifier

The private access modifier is accessible only within and not outside the class. Data members, methods, or constructors declared are strictly controlled. The private access modifier can not be accessed anywhere outside the class.

A Java class can not be private except for the nested class.

The complete program is listed below.

Step 1. First, we create a Java class PrivateExample in which we declare a private method run(): 

public class PrivateExample{    
    private void run() {  
        System.out.println("Scooter is running");  
    }  
}  

Step 2. Second, we create a class PrivateAccess in which we call the method of PrivateExample class:

public class PrivateAccess{  
        public static void main(String args[]) {  
            PrivateExample s = new PrivateExample();            
            s.run();  //compile time error
        }  
    }    

The output of the following code generates the following output.

 

Note 

In this example, we create two Java classes PrivateExample and PrivateAccess. PrivateExample contains private method run(). If we want to access the private method outside the class, it gives the compile-time error.

3) Protected access modifier.

The protected access modifier is accessible within and outside the package but through inheritance only.

The protected access modifiers can be applied to the variables, methods, and constructors but they can’t apply to Java classes. Variables, methods, and constructors are protected in a parent class and can be accessed by the child class in other packages. 

The complete program is listed below.

Step 1. First, we create a public Java class ProtectedExample in package pack1 in which we declare a protected method display().

package pack1;    
public class ProtectedExample{  
    protected void display() {  
        System.out.println("Protected access modifier example");    
    }  
}  

Step 2. Second, we create a public Java class ProtectedAccess in package pack2, which we call the method of ProtectedClass class.

package pack2;        
import pack1.*;        
public class ProtectedAcces extends ProtectedClass{        
    public static void main(String args[]) {        
        ProtectedAccess p = new ProtectedAccess();        
        p.display();    
    }    
}    

The output of the above code generates the following output.

 

4) Default access modifier

When we don’t use any modifier, it is treated as a default access modifier in Java. The default access modifier is only accessible only within the package.

Any Java class, Variable, method, and constructor, the default access modifier, is accessible only by the classes in the same package. The default access modifier is not used for variables and methods within an interface. 

The complete program is listed below.

Step 1. First, we create a default Java class named DefaultExample in package pack1 which we declare a method msg():

package pack1;    
 class DefaultExample {   
    void msg() {  
        System.out.println("Default access modifier example");  
    }  
}  

Step 2. Second, we create a default Java class DefaultAccess package named pack2 in which we call the method of DefaultClass class:

package pack2;    
import pack1.*;   
 class DefaultAccess{  
        public static void main(String args[]) {  
            DefaultClass d = new DefaultClass();// compile time error  
            r.msg(); // compile time error  
        }    
    }  

The output of the above code generates the following output.

 

Note

In this example, we create two Java classes DefaultClass and DefaultAccess. DefaultClass is a default Java class that can’t be accessed outside the package. So, it gives the compile-time error.

How many types of classes are in Java?

There are three major types of Java classes.

  1. Abstract Java Classes
  2. Nested Java Classes
  3. Final Java Classes
  4. Singleton Java class 

1) What is an Abstract class in Java?

Before Abstract Java classes, we should know about Abstraction in Java. 

Abstraction

In Java, Abstraction is a procedure to hide the implementation details from the user and provides only functionality to the user. For example, when we want to calculate some data in a calculator, we use its keys but don’t know how it works internally.    

So, when we use an abstract keyword with any class, this class is called an abstract Java class. It provides only essential things to the user and hides the internal process from the user. 

  1. Abstract Java class can have abstract methods and non-abstract methods.
  2. If a class has an abstract method, this class must be an abstract Java class.
  3. If we want to use an abstract class, it must be extended and its methods implemented.
  4. If we extend an abstract Java class, we have to provide the implementation for all abstract methods in it. 

The complete program is listed below.

Step 1. First, we create an abstract Java class named Employee in which we declare an abstract method called work().

abstract class AbstractClass {  
    abstract void work();  
} 

Step 2. Second, we create a public Java class named WomanEmployee in which we access the method work(), and its implementation is given by WomanEmployee class.

public class AbstractClass2 extends AbstractClass{    
    void work() {  
            System.out.println("Abstract class Example");  
        }  
        public static void main(String args[]) {  
            AbstractClass p = new AbstractClass2();  
            p.work();  
        }  
    }

The output of the following code generates the following output.

2) What are the Nested Java classes?

The Java programming language allows you to define a class within another class. We use the nested class to logically group the class and interface in one place. It can be more readable and maintainable and can access all the members of the outer class(public, private, protected).

Syntex 

class OuterClass{

…… 

      class InnerClass{ 

 //Nested Java class

}  

Advantages of nested class in Java

1. Nested Java classes show a special type of relationship; it can access all the members of the outer class, including private.

2. Nested Java classes are mainly used to make our program more readable and maintainable because it logically groups the classes and interfaces in one place.

3. Nested classes require less code to write.

Types of nested classes.

1. Non-static Nested Classes

2. Static-Nested Classes 

Non-static nested classes are also known as inner classes in Java.

Member inner class in Java

Member inner class is created inside the class but outside the method. It is a non-static inner class. Creating an inner member class in Java is simple. We need to write a class inside the class. The inner class can be private, and once we declare an inner class as confidential, it can not be accessed from an object outside the outer class.

Syntax 

class Outer{

     class Inner

      {

           // Member inner class 

      } 

The complete program is listed below.

public class MemberClassExample {  
    private int data = 30;    
    class MemberClassInner {  
        void msg() {  
            System.out.println("data is " + data);  
        }  
    }    
    public static void main(String args[]) {  
        MemberClassExample obj = new MemberClassExample();  
        MemberClassExample.MemberClassInner in = obj.new MemberClassInner();  
        in.msg();  
    }  
} 

The output of the following code generates the following output.

 

Note

In the example, we create a display() method in the inner member class, which access the private data member of the outer class.

Anonymous inner class in Java

The classes which have no name are called anonymous inner classes in Java. It must be used when we have to override the method of the class and interface.

We can declare and initiate them at the same time. The complete program is listed below.

public class AnonoymousClassExample {    
    public static void main(String[] args) {  
        AnonoymousDemo a = new AnonoymousDemo() {  
            public void message() {  
                System.out.println("Anonymous Inner Class Example");  
            }  
        }; // anonymous class body closes here  
        //a contains an object of anonymous subclass of AnonoymousClassExample.  
        a.message();  
    }  
}    
class AnonoymousDemo {  
    public void message() {  
        System.out.println("Message");  
    }  
}  

The output of the following code generates the following output.

 

Local inner class in Java

A Java class created inside the method is called a local inner class Java; if we want to call the methods of the local inner class, then we must initiate this class inside the method.

The complete program is listed below.

public class LocalInnerClassExample {  
    private int data = 30;    
    void display() {  
        class Local {  
            void msg() {  
                System.out.println(data);  
            }  
        }  
        Local l = new Local();  
        l.msg();  
    }   
    public static void main(String args[]) {  
        LocalInnerClassExample obj = new LocalInnerClassExample();  
        obj.display();  
    }  
} 

The output of the following code generates the following code.

 

Static nested class in Java 

A static class can not access non-static data members and methods. It can access static members of the outer class, whether private, public, or protected, and can only be accessed through the outer class name. When a static class is created inside another Java class, it is called a static nested class.

Syntax

class Outer{

       static NestedClass {

               // Static Nested class          

The complete program is listed below.

public class StaticNestedClassExample {  
    static int age = 30;    
    static class StaticClassAccess {  
        void display() {  
            System.out.println("Employee age is " + age);  
        }  
    }    
    public static void main(String args[]) {  
        StaticNestedClassExample.StaticClassAccess a = new StaticNestedClassExample.StaticClassAccess();  
        a.display();  
    }  
} 

The output of the following code generates the following output.

 

3) Final Java class 

When we use the final with any class, it is called a final Java class. A final class can’t be inherited. If any class is declared final, all its methods are implicitly declared as final. 

Syntax 

final class <class-name>{

       // code 

The complete program is listed below.

final  class FinalClassExample {    
}   
class Manager extends FinalClassExample {  // Compile time error  
    void work() {  
        System.out.println("working hard");  
    }   
    public static void main(String args[]) {  
        Manager m1 = new Manager();  
        m1.work();  
    }  
}  

The output of the following code generates the following output.

 

Note

In this example, we create a final Java class named FinalClassExample and another Java class named Manager. We try to inherit the final class, but the program makes a compile-time error.

4) Singleton Java Class

In object-oriented programming, a singleton class is a class that can have only one object at a time. Singletons often control access to resources, such as database connections or sockets. The intention is to create a single instance of an object of classes that are expensive to create during runtime and try to reuse the same object. Such objects are mainly immutable.

Some basic rules are required to implement a singleton class.

1. A constructor should be private.

2. Declare a static variable object of the class.

3. Declare a static method to return the instance.

The complete program is listed below.

Step 1. First, we create a singleton class named SingletonClassExample.

public class SingletonClassExample {  
    private static SingletonClassExample singleton = new SingletonClassExample();  
  
    public static SingletonClassExample getInstance() {  
        return singleton;  
    }  
  
    protected static void demoMethod() {  
        System.out.println("demoMethod for singleton");  
    }  
}  

Step 2. Second, we create a public class named SingleTonDemo for accessing the singleton class.

public class SingletonDemo {  
    public static void main(String[] args) {  
        SingletonClassExample tmp = SingletonClassExample.getInstance();  
        tmp.demoMethod();  
    }  
}  

The output of the following code generates the following output.

 

Summary

In this tutorial, we learned about various Java classes and how to use them in our java program.

Оригинальная статья: Dmitri Pavlutin – The Complete Guide to JavaScript Classes

JavaScript использует прототипное наследование: каждый объект наследует свойства и методы от своего объекта-прототипа. В нем не используется традиционный классовый подход для объектов, такой как в языках Java или Swift. Прототипное наследование имеет дело только с объектами.

Но через прототипное наследования можно эмулировать классическое наследование классов. Чтобы привести традиционные классы в JavaScript, в стандарте ES2015 было введено классовый синтаксис, то есть появилось ключевое слово class: которое является синтаксическим сахаром над прототипным наследованием.

Этот пост знакомит вас с классами в JavaScript: как определить класс, инициализировать экземпляр, определить поля и методы, рассматриваются такие понятия как приватные поля, публичные поля, статические поля и методы.

Содержание

  • 1. Определение: ключевое слово class
  • 2. Инициализация: constructor()
  • 3. Поля
    • 3.1 Публичные поля экземпляра
    • 3.2 Приватные поля экземпляра
    • 3.3 Публичные статические поля
    • 3.4 Приватные статические поля
  • 4. Методы
    • 4.1 Методы экземпляра
    • 4.2 Getters и setters
    • 4.3 Статические методы
  • 5. Наследование: extends
    • 5.1 Родительский конструктор: super() в constructor()
    • 5.2 Экземпляр родителя: super в методах
  • 6. Проверка типа объекта: instanceof
  • 7. Классы и прототипы
  • 8. Доступность возможностей классов
  • 9. Заключение

1. Определение: ключевое слово class

Специальное ключевое слово class определяет класс в JavaScript:

class User {
  // The body of class
}

Приведенный выше код определяет класс User. Фигурные скобки {} определяют тело класса. Обратите внимание, что такой синтаксис называется объявлением класса.

Вы не обязаны указывать название класса. Используя выражение класса, вы можете назначить класс переменной:

const UserClass = class {
  // The body of class
};

Вы можете легко экспортировать класс как часть модуля ES2015.

Вот синтаксис для экспорта по умолчанию:

export default class User {
 // The body of class
}

И именной экспорт:

export class User {
  // The body of class
}

Класс становится полезным, когда вы создаете экземпляр класса. Экземпляр – это объект, содержащий данные и поведение, описанные классом.

Оператор new создает экземпляр класса в JavaScript таким образом: instance = new Class().

Например, вы можете создать экземпляр класса User с помощью оператора new:

const myUser = new User();

new User() создает экземпляр класса User.

2. Инициализация: constructor()

constructor(param1, param2, …) это специальный метод в теле класса, который инициализирует экземпляр. Это место, где вы можете установить начальные значения для полей или выполнить любые настройки объектов.

В следующем примере конструктор устанавливает начальное значение поля name:

class User {
  constructor(name) {
    this.name = name;
  }
}

constructor класса User использует один параметр name, который используется для установки начального значения поля this.name.

Внутри конструктора значение this равно вновь созданному экземпляру.

Аргументы, используемые для создания экземпляра класса, становятся параметрами конструктора:

class User {
  constructor(name) {
    name; // => 'Jon Snow'
    this.name = name;
  }
}

const user = new User('Jon Snow');

Параметр name внутри конструктора имеет значение ‘Jon Snow’.

Если вы не определяете конструктор для класса, создается конструктор по умолчанию. Конструктор по умолчанию является пустой функцией, которая не изменяет экземпляр.

В то же время класс JavaScript может иметь до одного конструктора.

3. Поля

Поля класса являются переменными, которые содержат информацию. Поля могут быть привязаны к 2 объектам:

  1. Поля на экземпляре класса
  2. Поля на самом классе (в этом случае он называется статическим полем)

Поля также имеют 2 уровня доступности:

  1. Публичное: поле становиться везде доступным
  2. Приватное: поле доступно только внутри тела класса

3.1 Публичные поля экземпляра

Давайте снова посмотрим на предыдущий фрагмент кода:

class User {
  constructor(name) {
    this.name = name;
  }
}

Выражение this.name = name создает поля name экземпляра и присваивает ему начальное значение.

Позже вы можете получить доступ к полю name с помощью метода доступа к свойству:

const user = new User('Jon Snow');
user.name; // => 'Jon Snow'

name является публичным полем, поэтому вы можете получить к нему доступ вне тела класса User.

Когда поля создаются неявно внутри конструктора, как в предыдущем сценарии, их может быть сложно понять и интерпритировать в виде списка полей. Вам придется расшифровать их из кода конструктора.

Лучшим подходом является явное объявление полей класса. В этом случае независимо от того, что делает конструктор, экземпляр всегда будет иметь один и тот же набор полей.

Предложение (proposal) TC39 о полях класса позволяет определять поля внутри тела класса. Кроме того, вы можете сразу указать начальное значение:

class SomeClass {
  field1;
  field2 = 'Initial value';
  // ...
}

Давайте изменим класс User и объявим публичное поле name:

class User {
  name;  
  constructor(name) {
    this.name = name;
  }
}

const user = new User('Jon Snow');
user.name; // => 'Jon Snow'

name внутри тела класса объявляется как публичное поле.

После такого объявления достаточно быстрого просмотра полей, чтобы понять структуру данных класса.

Более того, поле класса может быть инициализировано сразу при объявлении.

class User {
  name = 'Unknown';
  constructor() {
    // No initialization
  }
}

const user = new User();
user.name; // => 'Unknown'

name = ‘Unknown’ внутри тела класса объявляет поля name и инициализирует его значением ‘Unknown’.

3.2 Приватные поля экземпляра

Инкапсуляция – это важная концепция, которая позволяет скрывать внутренние детали класса. Инкапсулированный класс, зависит только от открытого интерфейса, который предоставляет класс, и имеет полностью независимую внутреннюю реализацию класса.

Классы, организованные с учетом инкапсуляции, легче обновлять при изменении деталей реализации.

Хороший способ скрыть внутренние данные объекта – использовать приватные поля. Эти поля могут быть прочитаны и изменены только в пределах класса, к которому они принадлежат. Внешний мир класса не может напрямую изменять приватные поля.

Приватные поля доступны только внутри тела класса.

Для того что бы сделать поле приватным нужно использовать префикс # перед именем поля, например, #myField. Префикс # должен использоваться каждый раз, когда вы работаете с полем: объявление поле, получения или изменение значения.

Давайте удостоверимся, что поле #name будет приватным:

class User {
  #name;
  constructor(name) {
    this.#name = name;
  }

  getName() {
    return this.#name;
  }
}

const user = new User('Jon Snow');
user.getName(); // => 'Jon Snow'

user.#name;     // SyntaxError is thrown

Теперь #name это приватное поле. Вы можете получить доступ и изменить #name только в теле класса User. Метод getName() (подробнее о методах в следующем разделе) может получить доступ к закрытому полю #name.

Но если вы пытаетесь получить доступ к закрытому полю #name вне тела класса User, возникает синтаксическая ошибка: SyntaxError: Private field ‘#name’ must be declared in an enclosing class.

3.3 Публичные статические поля

Вы также можете определить поля для класса в этом случае они будут называться статические поля. Они полезны для определения констант класса или хранения информации, специфичной для этого класса.

Чтобы создать статические поля в классе JavaScript, используйте специальное ключевое слово static, за которым следует имя поля, например: static myStaticField.

Давайте добавим новый тип поля, который указывает тип пользователя: admin или regular. Статические поля TYPE_ADMIN и TYPE_REGULAR являются удобными константами для различения пользовательских типов:

class User {
  static TYPE_ADMIN = 'admin';
  static TYPE_REGULAR = 'regular';
  name;
  type;

  constructor(name, type) {
    this.name = name;
    this.type = type;
  }
}

const admin = new User('Site Admin', User.TYPE_ADMIN);
admin.type === User.TYPE_ADMIN; // => true

static TYPE_ADMIN и static TYPE_REGULAR определяют статические переменные внутри класса User. Чтобы получить доступ к статическим полям, вы должны использовать класс, за которым следует имя поля: User.TYPE_ADMIN и User.TYPE_REGULAR.

3.4 Приватные статические поля

Иногда даже статические поля – это детали реализации, которые вы хотели бы скрыть. В связи с этим вы можете сделать статические поля приватными.

Чтобы сделать статическое поле приватным, добавьте к имени поля специальный символ #, например: static #myPrivateStaticField.

Допустим, вы хотите ограничить количество экземпляров класса User. Чтобы скрыть подробности об ограничениях экземпляров, вы можете создать приватное статические поле:

class User {
  static #MAX_INSTANCES = 2;
  static #instances = 0;  
  name;

  constructor(name) {
    User.#instances++;
    if (User.#instances > User.#MAX_INSTANCES) {
      throw new Error('Unable to create User instance');
    }
    this.name = name;
  }
}

new User('Jon Snow');
new User('Arya Stark');
new User('Sansa Stark'); // throws Error

Статическое поле User.#MAX_INSTANCES устанавливает максимальное количество разрешенных экземпляров, в то время как статическое поле User.#instances подсчитывает фактическое количество экземпляров.

Эти частные статические поля доступны только внутри класса User. Ничто из внешнего мира не может помешать механизму ограничений: это преимущество инкапсуляции.

4. Методы

Поля содержат данные. Но возможность изменять данные выполняют специальные функции, которые являются частью класса: методы.

Классы JavaScript поддерживают как экземпляры, так и статические методы.

4.1 Методы экземпляра

Методы экземпляра могут обращаться к данным экземпляра и изменять их. Методы экземпляра могут вызывать другие методы экземпляра, а также любой статический метод.

Например, давайте определим метод getName(), который возвращает имя в классе User:

class User {
  name = 'Unknown';

  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

const user = new User('Jon Snow');
user.getName(); // => 'Jon Snow'

getName() {…} – это метод внутри класса User. А user.getName() – это вызов метода: он выполняет метод и возвращает вычисленное значение, если оно есть.

В методе класса, как и в конструкторе, значение this равно экземпляру класса. Используйте this для доступа к данным экземпляра, например: this.field или даже для вызова других методов, например: this.method().

Давайте добавим новый метод nameContains(str), который имеет один параметр и вызывает другой метод:

class User {
  name;

  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }

  nameContains(str) {
    return this.getName().includes(str);
  }
}

const user = new User('Jon Snow');
user.nameContains('Jon');   // => true
user.nameContains('Stark'); // => false

nameContains(str) {…} – это метод класса User, который принимает один параметр str. Более того, он выполняет другой метод экземпляра this.getName(), чтобы получить имя пользователя.

Метод также может быть закрытым. Чтобы сделать метод приватным, добавьте к его имени префикс #.

Давайте сделаем метод getName() приватным:

class User {
  #name;

  constructor(name) {
    this.#name = name;
  }

  #getName() {
    return this.#name;
  }
  nameContains(str) {
    return this.#getName().includes(str);
  }
}

const user = new User('Jon Snow');
user.nameContains('Jon');   // => true
user.nameContains('Stark'); // => false

user.#getName(); // SyntaxError is thrown

#getName() является приватным методом. Внутри метода nameContains(str) вызывается приватный метод this.#getName().

Будучи приватным, #getName() не может быть вызван вне тела класса User.

4.2 Getters и setters

getter и setter имитируют обычное поле, но с большим контролем над тем, как поле доступно.

getter выполняется при попытке получить значение поля, а setter при попытке установить значение.

Чтобы убедиться, что свойство name пользователя не может быть пустым, давайте обернем приватное поле #nameValue в методы getter и setter:

class User {
  #nameValue;

  constructor(name) {
    this.name = name;
  }

  get name() {    
    return this.#nameValue;
  }

  set name(name) {    
    if (name === '') {
      throw new Error(`name field of User cannot be empty`);
    }
    this.#nameValue = name;
  }
}

const user = new User('Jon Snow');
user.name; // The getter is invoked, => 'Jon Snow'
user.name = 'Jon White'; // The setter is invoked

user.name = ''; // The setter throws an Error

get name () {…} getter выполняется при доступе к значению поля user.name.

В то время как set name(name) {…}  выполняется при обновлении поля user.name = ‘Jon White’. setter выдаст ошибку, если новое значение будет пустой строкой.

4.3 Статические методы

Статические методы – это функции, прикрепленные непосредственно к классу. Они содержат логику, связанную с классом, а не с экземпляром класса.

Для создания статического метода используйте специальное ключевое слово static, за которым следует обычный синтаксис метода: static myStaticMethod () {…}.

При работе со статическими методами нужно помнить 2 простых правила:

  1. Статический метод может получить доступ к статическим полям
  2. Статический метод не может получить доступ к полям экземпляра.

Например, давайте создадим статический метод, который определяет, был ли уже выбран пользователь с определенным именем.

class User {
  static #takenNames = [];

  static isNameTaken(name) {    
    return User.#takenNames.includes(name);  
  }
  name = 'Unknown';

  constructor(name) {
    this.name = name;
    User.#takenNames.push(name);
  }
}

const user = new User('Jon Snow');

User.isNameTaken('Jon Snow');   // => true
User.isNameTaken('Arya Stark'); // => false

isNameTaken() – это статический метод, который использует статическое приватное поле User.#takeNames для проверки принятого значения name.

Статические методы могут быть приватными: static #staticFunction() {…}. Опять же, они следуют правилам конфиденциальности: вы можете вызывать приватный статический метод только внутри тела класса.

5. Наследование: extends

Классы в JavaScript поддерживают одиночное наследование с использованием ключевого слова extends.

Выражение вида class Child extends Parent { }, означает что класс Child наследует от класса Parent его конструктор, поля и методы.

Например, давайте создадим новый дочерний класс ContentWriter, который расширяет родительский класс User.

class User {
  name;

  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

class ContentWriter extends User {
  posts = [];
}

const writer = new ContentWriter('John Smith');

writer.name;      // => 'John Smith'
writer.getName(); // => 'John Smith'
writer.posts;     // => []

ContentWriter наследует от пользователя конструктор, метод getName() и поле name. Также, класс ContentWriter объявляет новое поле posts.

Обратите внимание, что приватные члены родительского класса не наследуются дочерним классом.

5.1 Родительский конструктор: super() в constructor()

Если вы хотите вызвать родительский конструктор в дочернем классе, вам нужно использовать специальную функцию super(), доступную в дочернем конструкторе.

Например, давайте сделаем так, чтобы конструктор ContentWriter вызывал родительский конструктор User, а также инициализировал поле posts:

class User {
  name;

  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

class ContentWriter extends User {
  posts = [];

  constructor(name, posts) {
    super(name);
    this.posts = posts;
  }
}

const writer = new ContentWriter('John Smith', ['Why I like JS']);
writer.name; // => 'John Smith'
writer.posts // => ['Why I like JS']

super(name) внутри дочернего класса ContentWriter выполняет конструктор родительского класса User.

Обратите внимание, что внутри дочернего конструктора вы должны выполнить super() перед использованием ключевого слова this. Вызов super() гарантирует, что родительский конструктор инициализирует экземпляр.

class Child extends Parent {
  constructor(value1, value2) {
    // Does not work!
    this.prop2 = value2;    
    super(value1);  
  }
}

5.2 Экземпляр родителя: super в методах

Если вы хотите получить доступ к родительскому методу внутри дочернего метода, вы можете использовать ключевое слово super.

class User {
  name;

  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

class ContentWriter extends User {
  posts = [];

  constructor(name, posts) {
    super(name);
    this.posts = posts;
  }

  getName() {
    const name = super.getName();    
    if (name === '') {
      return 'Unknown';
    }
    return name;
  }
}

const writer = new ContentWriter('', ['Why I like JS']);
writer.getName(); // => 'Unknown'

getName() дочернего класса ContentWriter обращается к методу super.getName() напрямую из родительского класса User.

Эта функция называется переопределением (overriding) метода.

Обратите внимание, что вы также можете использовать super со статическими методами для доступа к статическим методам родителя.

6. Проверка типа объекта: instanceof

object instanceof Class – оператор, который определяет, является ли object экземпляром Class.

Давайте посмотрим оператора instanceof в действии:

class User {
  name;

  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

const user = new User('Jon Snow');
const obj = {};

user instanceof User; // => true
obj instanceof User; // => false

user является экземпляром класса User, поэтому user instanceof User оценивается как true.

Пустой объект {} не является экземпляром User, соответственно obj instanceof User равен false.

instanceof является полиморфным: оператор обнаруживает дочерний элемент как экземпляр родительского класса.

class User {
  name;

  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

class ContentWriter extends User {
  posts = [];

  constructor(name, posts) {
    super(name);
    this.posts = posts;
  }
}

const writer = new ContentWriter('John Smith', ['Why I like JS']);

writer instanceof ContentWriter; // => true
writer instanceof User;          // => true

Writer является экземпляром дочернего класса ContentWriter. Оператор writer instanceof ContentWriter оценивается как true.

В то же время ContentWriter является дочерним классом User. Таким образом, writer instanceof User также оценивает как true.

Что если вы хотите определить точный класс экземпляра? Вы можете использовать свойство constructor и сравнить его непосредственно с классом:

writer.constructor === ContentWriter; // => true
writer.constructor === User;          // => false

7. Классы и прототипы

Я должен сказать, что синтаксис класса в JavaScript отлично справляется с абстрагированием от прототипного наследования. Для описания синтаксиса class я даже не использовал термин prototype.

Но внутри классы построены на основе прототипного наследования. Каждый класс является функцией и создает экземпляр при вызове в качестве конструктора.

Следующие два фрагмента кода эквивалентны.

Версия с классом:

class User {
  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

const user = new User('John');

user.getName();       // => 'John Snow'
user instanceof User; // => true

Версия с прототипом:

function User(name) {
  this.name = name;
}

User.prototype.getName = function() {
  return this.name;
}

const user = new User('John');

user.getName();       // => 'John Snow'
user instanceof User; // => true

Синтаксис класса намного проще в работе, если вы знакомы с классическим механизмом наследования языков Java или Swift.

В любом случае, даже если вы используете синтаксис класса в JavaScript, я рекомендую вам хорошо разбираться с прототипным наследованием (prototypal inheritance).

8. Наличие возможностей класса

Свойство классов, рассмотрены в этом посте, были внедрены в ES2015 а так же новыми предложениям (proposals) находящимися на этапе 3.

В конце 2019 года функции класса разделяются на:

  • Публичные и приватные поля экземпляра являются частью предложения TC39 о полях класса Class fields proposal
  • Приватные методы экземпляра и инструменты доступа являются частью предложения TC39 о приватных методов класса Class private methods proposal
  • Публичные и приватные статические поля и приватные статические методы являются частью предложения TC39 о статических функций класса Class static features proposal
  • Остальное является частью стандарта ES2015.

9. Заключение

Классы JavaScript инициализируют экземпляры конструкторами, определяют поля и методы. Вы можете прикрепить поля и методы даже к самому классу, используя ключевое слово static.

Наследование реализуется с помощью ключевого слова extends: вы можете легко создать дочерний класс из родительского. Ключевое слово super используется для доступа к родительскому классу из дочернего класса.

Чтобы воспользоваться преимуществами инкапсуляции, делайте поля и методы приватными, чтобы скрыть внутренние детали ваших классов. Имена приватных полей и методов должны начинаться с #.

Классы в JavaScript становятся все более удобными в использовании.

Была ли вам полезна эта статья?

Понравилась статья? Поделить с друзьями:

А вот и еще интересные новости по теме:

  • Инструкция по от для бухгалтера на предприятии
  • Tebonin intens 120 mg инструкция по применению
  • Урсосан 250 мг инструкция по применению цена отзывы врачей кардиологов
  • Массажер для ног гезатон инструкция по применению
  • Uno peg perego прогулочная коляска инструкция

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии