Co to jest „klasa abstrakcyjna” w Javie?
Co to jest „klasa abstrakcyjna” w Javie?
Odpowiedzi:
Klasa abstrakcyjna to klasa, której nie można utworzyć. Klasa abstrakcyjna jest używana przez tworzenie dziedziczącej podklasy, którą można utworzyć. Klasa abstrakcyjna wykonuje kilka czynności dla dziedziczącej podklasy:
Oto przykład:
abstract public class AbstractClass
{
abstract public void abstractMethod();
public void implementedMethod() { System.out.print("implementedMethod()"); }
final public void finalMethod() { System.out.print("finalMethod()"); }
}
Zauważ, że „abstractMethod ()” nie ma treści żadnej metody. Z tego powodu nie można wykonać następujących czynności:
public class ImplementingClass extends AbstractClass
{
// ERROR!
}
Nie ma metody, która implementuje abstractMethod()
! Dlatego JVM nie może wiedzieć, co ma zrobić, gdy coś się stanie new ImplementingClass().abstractMethod()
.
Oto poprawne ImplementingClass
.
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
}
Zauważ, że nie musisz definiować implementedMethod()
ani finalMethod()
. Zostały już zdefiniowane przez AbstractClass
.
Oto kolejna poprawna ImplementingClass
.
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
}
W tym przypadku zostało zastąpione implementedMethod()
.
Jednak ze względu na final
słowo kluczowe nie jest możliwe.
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
public void finalMethod() { System.out.print("ERROR!"); }
}
Nie możesz tego zrobić, ponieważ implementacja finalMethod()
in AbstractClass
jest oznaczona jako ostateczna implementacja finalMethod()
: żadne inne implementacje nie będą dozwolone.
Teraz możesz także dwukrotnie zaimplementować klasę abstrakcyjną:
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
}
// In a separate file.
public class SecondImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("second abstractMethod()"); }
}
Teraz gdzieś możesz napisać inną metodę.
public tryItOut()
{
ImplementingClass a = new ImplementingClass();
AbstractClass b = new ImplementingClass();
a.abstractMethod(); // prints "abstractMethod()"
a.implementedMethod(); // prints "Overridden!" <-- same
a.finalMethod(); // prints "finalMethod()"
b.abstractMethod(); // prints "abstractMethod()"
b.implementedMethod(); // prints "Overridden!" <-- same
b.finalMethod(); // prints "finalMethod()"
SecondImplementingClass c = new SecondImplementingClass();
AbstractClass d = new SecondImplementingClass();
c.abstractMethod(); // prints "second abstractMethod()"
c.implementedMethod(); // prints "implementedMethod()"
c.finalMethod(); // prints "finalMethod()"
d.abstractMethod(); // prints "second abstractMethod()"
d.implementedMethod(); // prints "implementedMethod()"
d.finalMethod(); // prints "finalMethod()"
}
Należy zauważyć, że chociaż ogłosił b
to AbstractClass
typ, wyświetla "Overriden!"
. Wynika to z faktu, że obiekt, który utworzyliśmy, był w rzeczywistości obiektem ImplementingClass
, który implementedMethod()
oczywiście jest przesłonięty. (Być może widzieliście to jako polimorfizm).
Jeśli chcemy uzyskać dostęp do członka określonego dla konkretnej podklasy, musimy najpierw przejść do tej podklasy:
// Say ImplementingClass also contains uniqueMethod()
// To access it, we use a cast to tell the runtime which type the object is
AbstractClass b = new ImplementingClass();
((ImplementingClass)b).uniqueMethod();
Wreszcie nie można wykonać następujących czynności:
public class ImplementingClass extends AbstractClass, SomeOtherAbstractClass
{
... // implementation
}
Jednorazowo można przedłużyć tylko jedną klasę. Jeśli chcesz rozszerzyć wiele klas, muszą to być interfejsy. Możesz to zrobić:
public class ImplementingClass extends AbstractClass implements InterfaceA, InterfaceB
{
... // implementation
}
Oto przykładowy interfejs:
interface InterfaceA
{
void interfaceMethod();
}
Jest to w zasadzie to samo, co:
abstract public class InterfaceA
{
abstract public void interfaceMethod();
}
Jedyną różnicą jest to, że drugi sposób nie pozwala kompilatorowi wiedzieć, że tak naprawdę jest interfejsem. Może to być przydatne, jeśli chcesz, aby ludzie implementowali tylko Twój interfejs, a nie innych. Jednak jako ogólna zasada dla początkujących, jeśli twoja klasa abstrakcyjna ma tylko metody abstrakcyjne, prawdopodobnie powinieneś uczynić ją interfejsem.
Następujące działania są nielegalne:
interface InterfaceB
{
void interfaceMethod() { System.out.print("ERROR!"); }
}
Nie można zaimplementować metod w interfejsie. Oznacza to, że jeśli zaimplementujesz dwa różne interfejsy, różne metody w tych interfejsach nie będą kolidować. Ponieważ wszystkie metody w interfejsie są abstrakcyjne, musisz zaimplementować metodę, a ponieważ twoja metoda jest jedyną implementacją w drzewie dziedziczenia, kompilator wie, że musi użyć twojej metody.
c.implementedMethod()
drukować „ Przesłonięcie !”? SecondImplementingClass
nie zastępuje implementedMethod()
.
Klasa Java staje się abstrakcyjna pod następującymi warunkami:
1. Co najmniej jedna z metod jest oznaczona jako abstrakcyjna:
public abstract void myMethod()
W takim przypadku kompilator zmusza do oznaczenia całej klasy jako abstrakcyjnej.
2. Klasa jest oznaczona jako abstrakcyjna:
abstract class MyClass
Jak już powiedziano: jeśli masz metodę abstrakcyjną, kompilator zmusza cię do oznaczenia całej klasy jako abstrakcyjnej. Ale nawet jeśli nie masz żadnej metody abstrakcyjnej, nadal możesz oznaczyć klasę jako abstrakcyjną.
Wspólne zastosowanie:
Powszechnym zastosowaniem klas abstrakcyjnych jest zapewnienie zarysu klasy podobnej do interfejsu. Jednak w przeciwieństwie do interfejsu może on już zapewniać funkcjonalność, tzn. Niektóre części klasy są zaimplementowane, a niektóre są po prostu opisane w deklaracji metody. ("abstrakcyjny")
Nie można utworzyć instancji klasy abstrakcyjnej, ale można utworzyć konkretną klasę na podstawie klasy abstrakcyjnej, którą można następnie utworzyć. Aby to zrobić, musisz odziedziczyć klasę abstrakcyjną i zastąpić metody abstrakcyjne, tj. Zaimplementować je.
abstract
słowo kluczowe jest wszystkim, co jest konieczne, aby klasa była abstrakcyjna. Ale konkretna klasa nie może zawierać abstract
metody . Dlatego jeśli twoja klasa ma abstract
metodę, musi zostać zadeklarowana jako abstract
kompilator dla kompilatora.
Klasa zadeklarowana za pomocą abstrakcyjnego słowa kluczowego jest znana jako abstract class
. Abstrakcja to proces ukrywania szczegółów implementacji danych i pokazywania użytkownikowi tylko funkcjonalności. Abstrakcja pozwala skupić się na tym, co robi obiekt, a nie na tym, jak to robi.
Główne rzeczy klasy abstrakcyjnej
Klasa abstrakcyjna może zawierać metody abstrakcyjne lub nie. Mogą być metody nieabstrakcyjne.
Metoda abstrakcyjna to metoda zadeklarowana bez implementacji (bez nawiasów klamrowych, po której następuje średnik), jak poniżej:
np .: abstract void moveTo(double deltaX, double deltaY);
Jeśli klasa ma co najmniej jedną metodę abstrakcyjną, klasa ta musi być abstrakcyjna
Klasy abstrakcyjne nie mogą być tworzone (nie wolno tworzyć obiektów klasy abstrakcyjnej)
Aby użyć klasy abstrakcyjnej, musisz odziedziczyć ją po innej klasie. Zapewnij implementacje do wszystkich zawartych w nim metod abstrakcyjnych.
Jeśli odziedziczysz klasę abstrakcyjną, musisz zapewnić implementacje wszystkich zawartych w niej metod abstrakcyjnych.
Zadeklaruj klasę abstrakcyjną
Podanie abstract
słowa kluczowego przed klasą podczas deklaracji czyni ją abstrakcyjną. Spójrz na poniższy kod:
abstract class AbstractDemo{ }
Zadeklaruj metodę abstrakcyjną
Podanie abstract
słowa kluczowego przed metodą podczas deklaracji czyni ją abstrakcyjną. Spójrz na poniższy kod,
abstract void moveTo();//no body
Dlaczego potrzebujemy abstrakcyjnych klas
W zorientowanej obiektowo aplikacji do rysowania możesz rysować koła, prostokąty, linie, krzywe Beziera i wiele innych obiektów graficznych. Wszystkie te obiekty mają wspólne wspólne stany (na przykład: położenie, orientacja, kolor linii, kolor wypełnienia) i zachowania (na przykład: moveTo, obracanie, zmiana rozmiaru, rysowanie). Niektóre z tych stanów i zachowań są takie same dla wszystkich obiektów graficznych (np. Kolor wypełnienia, pozycja i moveTo). Inne wymagają innej implementacji (np. Zmiana rozmiaru lub losowanie). Wszystkie obiekty graficzne muszą mieć możliwość rysowania lub zmiany rozmiaru, różnią się jedynie sposobem, w jaki to robią.
To idealna sytuacja dla abstrakcyjnej nadklasy. Możesz skorzystać z podobieństw i zadeklarować wszystkie obiekty graficzne do dziedziczenia z tego samego abstrakcyjnego obiektu nadrzędnego (np.:), GraphicObject
Jak pokazano na poniższym rysunku.
Najpierw deklarujesz klasę abstrakcyjną GraphicObject
, aby zapewnić zmienne składowe i metody, które są w pełni współdzielone przez wszystkie podklasy, takie jak bieżąca pozycja i metoda moveTo. GraphicObject
zadeklarował również metody abstrakcyjne, takie jak rysowanie lub zmiana rozmiaru, które muszą być zaimplementowane przez wszystkie podklasy, ale muszą być zaimplementowane na różne sposoby. GraphicObject
Klasa może wyglądać następująco:
abstract class GraphicObject {
void moveTo(int x, int y) {
// Inside this method we have to change the position of the graphic
// object according to x,y
// This is the same in every GraphicObject. Then we can implement here.
}
abstract void draw(); // But every GraphicObject drawing case is
// unique, not common. Then we have to create that
// case inside each class. Then create these
// methods as abstract
abstract void resize();
}
Zastosowanie metody abstrakcyjnej w podklasach
Każda nie abstrakcyjna podklasa GraphicObject
, taka jak Circle
i Rectangle
, musi zapewniać implementacje dla metod draw
i resize
.
class Circle extends GraphicObject {
void draw() {
//Add to some implementation here
}
void resize() {
//Add to some implementation here
}
}
class Rectangle extends GraphicObject {
void draw() {
//Add to some implementation here
}
void resize() {
//Add to some implementation here
}
}
Wewnątrz main
metody możesz wywołać wszystkie takie metody:
public static void main(String args[]){
GraphicObject c = new Circle();
c.draw();
c.resize();
c.moveTo(4,5);
}
Sposoby osiągnięcia abstrakcji w Javie
Istnieją dwa sposoby osiągnięcia abstrakcji w java
Klasa abstrakcyjna z konstruktorami, elementami danych, metodami itp
abstract class GraphicObject {
GraphicObject (){
System.out.println("GraphicObject is created");
}
void moveTo(int y, int x) {
System.out.println("Change position according to "+ x+ " and " + y);
}
abstract void draw();
}
class Circle extends GraphicObject {
void draw() {
System.out.println("Draw the Circle");
}
}
class TestAbstract {
public static void main(String args[]){
GraphicObject grObj = new Circle ();
grObj.draw();
grObj.moveTo(4,6);
}
}
Wynik:
GraphicObject is created
Draw the Circle
Change position according to 6 and 4
Pamiętaj o dwóch zasadach:
Jeśli klasa ma kilka metod abstrakcyjnych i kilka konkretnych metod, zadeklaruj ją jako abstract
klasę.
Jeśli klasa ma tylko abstrakcyjne metody, zadeklaruj ją jako interface
.
Bibliografia:
Jest to klasa, której nie można utworzyć instancji, i zmusza implementację klas do ewentualnego wdrożenia abstrakcyjnych metod, które określa.
Mówiąc najprościej, możesz myśleć o klasie abstrakcyjnej jak o interfejsie z nieco większymi możliwościami.
Nie można utworzyć instancji interfejsu, który dotyczy również klasy abstrakcyjnej.
W interfejsie możesz po prostu zdefiniować nagłówki metod, a WSZYSTKIE implementatory są zmuszone do implementacji wszystkich . W klasie abstrakcyjnej możesz również zdefiniować nagłówki metody, ale tutaj - w odróżnieniu od interfejsu - możesz także zdefiniować treść (zwykle domyślną implementację) metody. Ponadto, gdy inne klasy rozszerzają (uwaga, nie implementuj, a zatem możesz mieć tylko jedną klasę abstrakcyjną na klasę podrzędną) swoją klasę abstrakcyjną, nie są zmuszone do implementacji wszystkich metod klasy abstrakcyjnej, chyba że podasz metodę abstrakcyjną ( w takim przypadku działa jak w przypadku interfejsów, nie można zdefiniować treści metody).
public abstract class MyAbstractClass{
public abstract void DoSomething();
}
W przeciwnym razie w przypadku normalnych metod klasy abstrakcyjnej „dziedziczący” mogą po prostu użyć domyślnego zachowania lub go zastąpić, jak zwykle.
Przykład:
public abstract class MyAbstractClass{
public int CalculateCost(int amount){
//do some default calculations
//this can be overriden by subclasses if needed
}
//this MUST be implemented by subclasses
public abstract void DoSomething();
}
Z dokumentacji wyroczni
Metody i klasy abstrakcyjne:
Klasa abstrakcyjna to klasa, która jest zadeklarowana jako abstrakcyjna - może zawierać lub nie metody abstrakcyjne
Klasy abstrakcyjne nie mogą być tworzone, ale można je podklasować
Metoda abstrakcyjna to metoda zadeklarowana bez implementacji (bez nawiasów klamrowych, po której następuje średnik), jak poniżej:
abstract void moveTo(double deltaX, double deltaY);
Jeśli klasa zawiera metody abstrakcyjne, sama klasa musi zostać zadeklarowana jako abstrakcyjna, jak w:
public abstract class GraphicObject {
// declare fields
// declare nonabstract methods
abstract void draw();
}
Kiedy klasa abstrakcyjna jest podklasowana, podklasa zwykle zapewnia implementacje dla wszystkich metod abstrakcyjnych w swojej klasie nadrzędnej. Jeśli jednak tak nie jest, podklasę należy również uznać za abstrakcyjną .
Ponieważ abstract classes
i interfaces
są powiązane, spójrz na poniższe pytania SE:
Jaka jest różnica między interfejsem a klasą abstrakcyjną?
Jak powinienem wyjaśnić różnicę między interfejsem a klasą abstrakcyjną?
Uzyskaj odpowiedzi tutaj:
Klasa abstrakcyjna vs Interfejs w Javie
Czy klasa abstrakcyjna może mieć ostateczną metodę?
BTW - to są pytania, które zadałeś ostatnio. Pomyśl o nowym pytaniu, aby zbudować reputację ...
Edytować:
Właśnie zdałem sobie sprawę, że plakaty tego i odnośników mają taką samą lub przynajmniej podobną nazwę, ale identyfikator użytkownika jest zawsze inny. Tak więc albo istnieje problem techniczny, że keyur ma problemy z ponownym zalogowaniem się i znalezieniem odpowiedzi na swoje pytania, lub jest to rodzaj gry zapewniającej rozrywkę społeczności SO;)
Mały dodatek do wszystkich tych postów.
Czasami możesz chcieć zadeklarować klasę, ale nie wiesz, jak zdefiniować wszystkie metody należące do tej klasy. Na przykład możesz zadeklarować klasę o nazwie Writer i dołączyć do niej metodę członka o nazwie write () . Nie wiesz jednak, jak kodować write (), ponieważ różni się dla każdego typu urządzeń Writer. Oczywiście planujesz sobie z tym poradzić, wyprowadzając podklasę Writer, taką jak Drukarka, Dysk, Sieć i Konsola.
Klasa abstrakcyjna nie może być bezpośrednio utworzona, ale musi być pochodną, aby była użyteczna. Klasa MUSI być abstrakcyjna, jeśli zawiera metody abstrakcyjne: albo bezpośrednio
abstract class Foo {
abstract void someMethod();
}
lub pośrednio
interface IFoo {
void someMethod();
}
abstract class Foo2 implements IFoo {
}
Jednak klasa może być abstrakcyjna bez zawierania metod abstrakcyjnych. Jest to sposób na zapobieganie bezpośredniej instancji, np
abstract class Foo3 {
}
class Bar extends Foo3 {
}
Foo3 myVar = new Foo3(); // illegal! class is abstract
Foo3 myVar = new Bar(); // allowed!
Ten ostatni styl klas abstrakcyjnych można wykorzystać do tworzenia klas „podobnych do interfejsu”. W przeciwieństwie do interfejsów klasa abstrakcyjna może zawierać nieabstrakcyjne metody i zmienne instancji. Możesz użyć tego, aby zapewnić podstawową funkcjonalność rozszerzania klas.
Innym częstym wzorcem jest implementacja głównej funkcjonalności w klasie abstrakcyjnej i zdefiniowanie części algorytmu w metodzie abstrakcyjnej, która ma zostać zaimplementowana przez rozszerzającą się klasę. Głupi przykład:
abstract class Processor {
protected abstract int[] filterInput(int[] unfiltered);
public int process(int[] values) {
int[] filtered = filterInput(values);
// do something with filtered input
}
}
class EvenValues extends Processor {
protected int[] filterInput(int[] unfiltered) {
// remove odd numbers
}
}
class OddValues extends Processor {
protected int[] filterInput(int[] unfiltered) {
// remove even numbers
}
}
public abstract class Place {
String Name;
String Postcode;
String County;
String Area;
Place () {
}
public static Place make(String Incoming) {
if (Incoming.length() < 61) return (null);
String Name = (Incoming.substring(4,26)).trim();
String County = (Incoming.substring(27,48)).trim();
String Postcode = (Incoming.substring(48,61)).trim();
String Area = (Incoming.substring(61)).trim();
Place created;
if (Name.equalsIgnoreCase(Area)) {
created = new Area(Area,County,Postcode);
} else {
created = new District(Name,County,Postcode,Area);
}
return (created);
}
public String getName() {
return (Name);
}
public String getPostcode() {
return (Postcode);
}
public String getCounty() {
return (County);
}
public abstract String getArea();
}
Klasa abstrakcyjna to klasa, która jest zadeklarowana jako abstrakcyjna - może zawierać metody abstrakcyjne lub nie. Klasy abstrakcyjne nie mogą być tworzone, ale można je podklasować.
Innymi słowy, klasa zadeklarowana za pomocą abstrakcyjnego słowa kluczowego jest znana w Javie jako klasa abstrakcyjna. Może mieć metody abstrakcyjne (metoda bez ciała) i metody nieabstrakcyjne (metoda z ciałem).
Ważna uwaga: - Klasy abstrakcyjne nie mogą być używane do tworzenia instancji obiektów, można ich używać do tworzenia odwołań do obiektów, ponieważ podejście Javy do polimorfizmu w czasie wykonywania jest implementowane za pomocą odwołań do nadklasy. Dlatego musi istnieć możliwość utworzenia odwołania do klasy abstrakcyjnej, aby można było jej użyć do wskazania obiektu podklasy. Zobaczysz tę funkcję w poniższym przykładzie
abstract class Bike{
abstract void run();
}
class Honda4 extends Bike{
void run(){
System.out.println("running safely..");
}
public static void main(String args[]){
Bike obj = new Honda4();
obj.run();
}
}
Klasa abstrakcyjna to klasa, która nie jest w pełni zaimplementowana, ale zapewnia coś w rodzaju schematu dla podklas. Może być częściowo zaimplementowany, ponieważ zawiera w pełni zdefiniowane konkretne metody, ale może także zawierać metody abstrakcyjne. Są to metody z podpisem, ale bez treści metody. Każda podklasa musi definiować treść dla każdej metody abstrakcyjnej, w przeciwnym razie również musi zostać uznana za abstrakcyjną. Ponieważ klasy abstrakcyjne nie mogą być tworzone, muszą zostać rozszerzone o co najmniej jedną podklasę, aby można je było wykorzystać. Pomyśl o klasie abstrakcyjnej jak o klasie ogólnej, a podklasy służą do uzupełnienia brakujących informacji.
Nic nie robi, wystarczy podać wspólny szablon, który zostanie udostępniony dla jego podklasy