Java поддерживает наследование классов. Класс от которого наследуются называется суперклассом. Класс, который наследуется называется подклассом. При этом подкласс получает доступ ко все членам (переменным и методам) за исключением приватных (с модификатором доступа private). К приватным можно добраться не через приватные, например приватные переменные суперкласса можно устанавливать через неприватные (например protected) методы суперкласса.
class A { private int PrivateValue = 1; int valueA = 1; void ShowA(){ JOptionPane.showMessageDialog(null, "Method A"); }
}
class B extends A{ int valueB = 10; void ShowB(){ JOptionPane.showMessageDialog(null, "Method B"); }
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { B b = new B(); //унаследовали от суперкласса b.valueA = 1; b.ShowA(); //собственные методы и переменные b.valueB = 1; b.ShowB(); //b.PrivateValue = 1; - ошибка переменная в суперклассе объявлена как private
}
Переменная суперкласса может ссылаться на любой объект подкласса. Этим достигается полиморфизм времени выполнения. Мы можем иметь переменную суперкласса и присваивать ей ссылку на любой объект подкласса, при этом вызывать один и тот же метод. Вызываться будет метод того объекта на который в данный момент ссылается переменная суперкласса.
//суперкласс First class First{ void ShowMessage(){JOptionPane.showMessageDialog(null, "First Class Method");} }
//подкласс Second перекрывает метод ShowMessage class Second extends First{ void ShowMessage(){JOptionPane.showMessageDialog(null, "Second Class Method");} }
//подкласс Third перекрывает метод ShowMessage class Third extends Second{ void ShowMessage(){JOptionPane.showMessageDialog(null, "Third Class Method");} }
//Переменная суперкласса может ссылаться на любой объект подкласса First f1 = new First(); f1.ShowMessage();
//Динамическая диспетчеризация метода - так как ShowMessage перекрыт в Second, вызываться будет метод //реального объекта на который ссылается переменная, а не тот, который соответсвует типу переменной First f2 = new Second(); f2.ShowMessage();
//Динамическая диспетчеризация метода - так как ShowMessage перекрыт в Third, вызываться будет метод //реального объекта на который ссылается переменная, а не тот, который соответсвует типу переменной First f3 = new Third(); f3.ShowMessage();
Мы можем перекрыть метод или переменную суперкласса в подклассе. Для того, чтобы получить доступ к ним из подкласса нужно использовать ключевое слово super. Также оно используется для вызова конструктора суперкласса.
class Box { //объявляем приватные переменные в классе private int width, height, depth; //объявляем конструктор с инициализацией Box(int w, int h, int d){ this.width = w; this.height = h; this.depth = d; }
//объявляем конструктор по умолчания Box(){ this.width = this.height = this.depth = -1; //width = height = depth = -1; //можно и вот так без "this" }
void ShowMessage(){JOptionPane.showMessageDialog(null, "In the Box");} }
class ColorBox extends Box{ //добавляем новую переменную к классу int color; ColorBox(int w, int h, int d, int c){ //так как переменные суперкласса width, height, depth приватные и //непосредственного доступа отсюда к ним нет - то инициализировать можно //только через "super" super(w, h, d); this.color = c; }
ColorBox(){ //конструктор по умолчанию из суперкласса super(); color = -1; }
//перекрыли метод суперкласса @Override void ShowMessage(){JOptionPane.showMessageDialog(null, "In the ColorBox");}
//вызываем метод текущего объекта void Alert(){ShowMessage();} //вызываем метод суперкласса через super void SuperAlert(){super.ShowMessage();} }
ColorBox cb = new ColorBox(1, 2, 3, 4); //вызываем метод ColorBox cb.Alert(); //вызываем метод Box через super cb.SuperAlert();
Класс может содержать абстрактные методы без реализации. В этом случае он сам должен быть помечен как абстрактный (abstract). Абстрактный класс может содержать переменные и не абстрактные методы. Во всех подклассах все абстрактные методы должны быть реализованы.
//абстрактный суперкласс abstract class A { //абстрактный класс может содержать переменные int value1; String value2; //это абстрактные методы - они должны быть реализованы в подклассе abstract void Method1(); abstract void Method2(); abstract Object Method3(); //абстрактный класс может содержать методы с реализацией (неабстратные) String Method4(){return "Привет";} }
//подкласс с реализацией class B extends A{ //реализация абстрактных методов @Override void Method1(){JOptionPane.showMessageDialog(null, "Method1");} @Override void Method2(){JOptionPane.showMessageDialog(null, "Method2");} @Override Object Method3(){return new Object();}
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
A SuperObject; B b = new B();
//переменная суперкласса ссылается на объект подкласса SuperObject = b; SuperObject.Method1(); SuperObject.Method2(); JOptionPane.showMessageDialog(null, SuperObject.Method4());
}
Мы можем запретить перекрывать методы в подклассах, для этого нужно пометить его директивой final. Чтобы запретить наследовать от класса, мы должны пометить его как final.
//этот класс можно наследовать class A{ void Method1(){JOptionPane.showMessageDialog(null, "Этот метод можно перекрыть в подклассах");} final void Method2(){JOptionPane.showMessageDialog(null, "Этот метод нельзя перекрыть в подклассах");} }
//этот класс нельзя наследовать - объявлен как final final class B extends A{ void Method1(){JOptionPane.showMessageDialog(null, "Перекрыли метод");} //@Override final void Method2(){JOptionPane.showMessageDialog(null, "Этот метод нельзя перекрыть в подклассах");} // в суперклассе он объявлен как "final" }
//class C extends B {} нельзя наследовать от класса B - он объявлен как final
|