Skip to content

Latest commit

 

History

History
334 lines (271 loc) · 18.8 KB

lab10.md

File metadata and controls

334 lines (271 loc) · 18.8 KB

10. Наследование

Наследование

Наследование позволяет создавать новые классы на основе существующих, расширяя состояние и поведение объектов новыми свойствами и методами соответственно.

Суперкласс и подклассы

Суперкласс (Базовый класс) --- это класс, от которого наследуются другие классы.

В Kotlin, классы по умолчанию являются завершенными final, что означает, что они не могут быть унаследованы. Чтобы разрешить наследование, класс должен быть помечен ключевым словом open.

// Суперкласс для представления графических фигур
open class Shape {
    var x: Int = 0
    var y: Int = 0
       
    fun move(dx: Int; dy: Int) {
	    x += dx
	    y += dy
    }
}

Подкласс (Производный класс) --- это класс, который наследует свойства и методы от базового класса.

Подкласс создается с помощью ключевого слова class, за которым следует имя класса и двоеточие, а затем имя суперкласса.

// Подкласс для представления прямоугольников
class Rectangle: Shape {
	var width: Int = 1
	var height: Int = 1
	
    fun draw(Graphics2D g2d) {
        g2d.fillRect(x, y, width, height)
    }
}

Переопределение методов и свойств

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

// Суперкласс для представления графических фигур
open class Shape {
    var x: Int = 0
    var y: Int = 0

	// Откытое для переопределения в подклассах свойство 
	open val defaultColor : Color = Color.BLACK 
	
	// Откытый для переопределения в подклассах метод
    open fun draw(g2d: Graphics2D) {
    }
}

// Подкласс для представления прямоугольников
class Rectangle: Shape() {
	var width: Int = 1
	var height: Int = 1

	// Переопределение свойства, унаследованного от суперкласса 
    override val defaultColor : Color = Color.RED
    
	// Переопределение метода, унаследованного от суперкласса 
    override fun draw(Graphics2D g2d) {
	g2d.color = defaultColor
        g2d.fillRect(x, y, width, height)
    }
}

Член класса, помеченный override, доступен для переопределения в производных классах. Чтобы сделать его завершенным (т.е. запретить возможность его переопределения), в объявление должен быть включен модификатор final.

open class Rectangle() : Shape() {
	// ... 
    final override fun draw() { 
	    g2d.fillRect(x, y, width, height)
    }
}

Обращение к конструкторам суперкласса

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

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

// Суперкласс для представления графических фигур с первичным конструктором
open class Shape (  
	var x: Int = 0,  
	var y: Int = 0  
) {  
	open val defaultColor : Color = Color.BLACK
	open fun draw(g2d: Graphics2D) {  
	}  
}  

// Подкласс для представления прямоугольников с первичным конструктором
class Rectangle(  
	x: Int = 0,  
	y: Int = 0,  
	var width: Int = 1,  
	var height: Int = 1  
) : Shape(x, y) {  
	override val defaultColor : Color = Color.RED
	override fun draw(g2d: Graphics2D) {
		g2d.color = defaultColor
		g2d.fillRect(x, y, width, height)  
	}  
}

Вторичные конструкторы суперкласса

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

// Суперкласс для представления графических фигур со вторичным конструктором
abstract class Shape {  
	var x: Int = 0  
	var y: Int = 0
	
	// Вторичный конструктор
	.. 
	constructor(x: Int, y: Int) {  
		this.x = x  
		this.y = y  
	}  
	abstract fun draw(g2d: Graphics2D)  
}  

// Подкласс для представления прямоугольников со вторичным конструктором
class Rectangle: Shape {  
	var width: Int = 1  
	var height: Int = 1  
	
	// Вторичный конструктор  
	constructor(x: Int, y: Int, width: Int, height: Int): super(x, y) {  
		this.width = width  
		this.height = height  
	}  
	  
	override fun draw(g2d: Graphics2D) {  
		g2d.fillRect(x, y, width, height)  
	}  
}

Вызов конструктора подкласса для создании объектов

При создании объектов подклассов, параметры передаются через конструктор подкласса в конструктор суперкласса.

fun main() {
    val rectangle = Rectangle(50, 50, 200, 100)
    rectangle.draw()
}

Использование наследования

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

fun main() {
    val rect = Rectangle(250, 250, 10, 20)
    
    // Создаем растровое изображение размером 400x300 пикселей
    val image = BufferedImage(400, 300, BufferedImage.TYPE_INT_ARGB)
    // Получаем графический контекст для рисования на изображении
    val g2d = image.createGraphics()
	// Вывод прямоугольника на графический контекст
    rect.draw(g2d)  
}

Абстрактные классы

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

// Абстрактный суперкласс для представления графических фигур
abstract class Shape (  
	var x: Int = 0,  
	var y: Int = 0  
) { 
	// Абстрактный метод
	abstract fun draw(g2d: Graphics2D)  
}  

// Подкласс для представления прямоугольников
class Rectangle(  
	x: Int = 0,  
	y: Int = 0,  
	var width: Int = 1,  
	var height: Int = 1  
) : Shape(x, y) {
	// Определение абстрактного метода, унаследованного от суперкласса
	override fun draw(g2d: Graphics2D) {  
		g2d.fillRect(x, y, width, height)  
	}  
}

Изолированные (sealed) классы

...

...

...

Задание

Часть I Создание базовой иерархии классов для представления графических фигур с использованием наследования

Требования:

  • Создайте абстрактный класс AreaShape для представления абстрактных площадных графических фигур:

    • Должны быть объявлены следующие свойства:
      • x, y координаты базовой точки
      • color (цвет фигуры)
    • Должен быть реализован конструктор
    • Должен быть объявлен и реализован метод
      • move(dx: Int, dy: Int) для перемещения фигуры на заданное расстояние
    • Должен быть объявлен абстрактный метод
      • draw(g2d: Graphics2D) для отрисовки фигуры на графическом контексте
      • area() для вычисления площади фигуры
  • Создайте класс Rectangle, расширяющий класс AreaShape, для представления прямоугольников:

    • Должны быть объявлены следующие свойства:
      • width, height ширина и высота
    • Должны быть переопределены следующие методы:
      • draw(g2d: Graphics2D): отрисовывает прямоугольник на графическом контексте.
      • area(): возвращает площадь прямоугольника.
  • Создайте класс Ellipse, расширяющий класс Rectangle, для представления эллипсов.

    • Должны быть переопределены следующие методы:
      • draw(g2d: Graphics2D): отрисовывает эллипс на графическом контексте.
      • area(): возвращает площадь эллипса.
  • Создайте несколько графических фигур и вычислите их площадь

Часть II Создание расширенной иерархии классов для представления графических фигур с использованием наследования:

Требования:

  • Создайте абстрактный класс Shape для представления абстрактных графических фигур:

    • Должны быть объявлены следующие свойства:
      • x, y координаты базовой точки
      • angle угол поворота (в градусах)
      • strokeColor (цвет контура фигуры)
    • Должен быть реализован конструктор
    • Должны быть объявлены и реализованы следующие методы:
      • move(dx: Int, dy: Int) для перемещения фигуры на заданное расстояние
      • rotate(angle: Int) для поворота фигуры на заданный угол (в градусах)
    • Должен быть объявлен абстрактный метод
      • draw(g2d: Graphics2D) для отрисовки фигуры на графическом контексте
  • Создайте абстрактный класс AreaShape, расширяющий класс Shape, для представления абстрактных площадных графических фигур:

    • Должны быть объявлены следующие свойства:
      • width, height ширина и высота описанного прямоугольника
      • fillColor (цвет заливки фигуры)
    • Должен быть реализован конструктор
    • Должны быть объявлены и реализованы следующие методы:
      • scale(factor: Double) для масштабирования фигуры с общим фактором для двух осей
      • scale(xFactor: Double, yFactor: Double) для масштабирования фигуры с разными факторами
    • Должны быть объявлены следующие абстрактные методы
      • draw(g2d: Graphics2D) для отрисовки фигуры на графическом контексте
      • area() для вычисления площади фигуры
  • Создайте класс Rectangle, расширяющий класс AreaShape, для представления прямоугольников:

    • Должны быть переопределены следующие методы:
      • draw(g2d: Graphics2D): отрисовывает прямоугольник на графическом контексте.
      • area(): возвращает площадь прямоугольника.
  • Создайте класс Ellipse, расширяющий класс AreaShape, для представления эллипсов.

    • Должны быть переопределены следующие методы:
      • draw(g2d: Graphics2D): отрисовывает эллипс на графическом контексте.
      • area(): возвращает площадь эллипса.
  • Создайте класс Line, расширяющий класс Shape, для представления эллипсов.

    • Должны быть объявлены следующие свойства:
      • x2, y2 координаты конечной точки линии
    • Должен быть переопределен метод:
      • draw(g2d: Graphics2D): отрисовывает линию на графическом контексте.
  • Создайте класс Text, расширяющий класс Shape, для представления текста.

    • Должны быть объявлены следующие свойства:
      • text текст
    • Должен быть переопределен метод:
      • draw(g2d: Graphics2D): отрисовывает текст на графическом контексте.
  • Создайте несколько графических фигур и выведите их изображение в файл формата PNG.

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

Часть III Разработать приложение командной строки, которое позволяет рисовать три вида диаграмм (график, столбчатая, круговая).

Требования:

  • Создайте абстрактный класс диаграмм Chart с абстрактным методом draw().
  • Реализуйте три класса, наследующиеся от Chart: LineChart (график), BarChart (столбчатая диаграмма) и PieChart (круговая диаграмма).
  • Каждый класс должен реализовывать метод draw() для рисования соответствующего типа диаграммы.
  • Создайте класс ChartFactory, который будет создавать объекты Chart в зависимости от типа диаграммы.
  • Реализуйте функцию main(), которая считывает входные данные, создает объект Chart с помощью ChartFactory и вызывает метод draw().
  • Входные данные должны задаваться пользователем в командной строке.
  • Пользователь должен иметь возможность настройки следующих параметров:
    • Цвета используемые в диаграммах (для графиков и столбчатых диаграмм)
    • Текстовые подписи осей координат (для графиков и столбчатых диаграмм)
    • Размер диаграммы (для всех видов диаграмм)
    • Легенда (для круговых диаграмм)
  • Диаграммы должны выводиться на графический контекст, а их изображения должны сохраняться в файлы в формате PNG.

Вопросы

  1. Наследование
  2. Суперкласс / Подкласс
  3. Базовый класс / Производный класс
  4. Абстрактный класс
  5. Абстрактный метод
  6. Переопределение свойств
  7. Переопределение методов
  8. Полиморфизм

Ресурсы