Java에서 "추상 클래스"란 무엇입니까?
Java에서 "추상 클래스"란 무엇입니까?
답변:
추상 클래스는 인스턴스화 할 수없는 클래스입니다. 추상 클래스는 인스턴스화 할 수 있는 상속 서브 클래스를 작성하여 사용됩니다 . 추상 클래스는 상속 서브 클래스에 대해 몇 가지 작업을 수행합니다.
예를 들면 다음과 같습니다.
abstract public class AbstractClass
{
abstract public void abstractMethod();
public void implementedMethod() { System.out.print("implementedMethod()"); }
final public void finalMethod() { System.out.print("finalMethod()"); }
}
"abstractMethod ()"에는 메소드 본문이 없습니다. 이로 인해 다음을 수행 할 수 없습니다.
public class ImplementingClass extends AbstractClass
{
// ERROR!
}
구현하는 메소드가 없습니다 abstractMethod()
! 따라서 JVM이 다음과 같은 것을 얻을 때 수행해야 할 작업을 알 수있는 방법이 없습니다 new ImplementingClass().abstractMethod()
.
올바른 내용은 다음과 같습니다 ImplementingClass
.
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
}
implementedMethod()
또는 을 정의 할 필요는 없습니다 finalMethod()
. 이미에 의해 정의되었습니다 AbstractClass
.
또 다른 올바른 것이 ImplementingClass
있습니다.
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
}
이 경우을 재정의했습니다 implementedMethod()
.
그러나 final
키워드로 인해 다음이 불가능합니다.
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!"); }
}
finalMethod()
in AbstractClass
구현이 최종 구현으로 표시되어 있기 때문에이 작업을 수행 할 수 없습니다 finalMethod()
. 다른 구현은 절대 허용되지 않습니다.
이제 추상 클래스를 두 번 구현할 수도 있습니다 .
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()"); }
}
이제 어딘가에 다른 방법을 쓸 수 있습니다.
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()"
}
우리가 선언에도 불구하고 있음을 공지 유형에서 표시 . 우리가 인스턴스화 된 객체가 실제로이었다 때문입니다 누구는 물론 오버라이드 (override)이다. (이것을 다형성이라고합니다.)b
AbstractClass
"Overriden!"
ImplementingClass
implementedMethod()
특정 하위 클래스에 특정한 멤버에 액세스하려면 먼저 해당 하위 클래스로 캐스트해야합니다.
// 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();
마지막으로 다음을 수행 할 수 없습니다.
public class ImplementingClass extends AbstractClass, SomeOtherAbstractClass
{
... // implementation
}
한 번에 하나의 수업 만 연장 할 수 있습니다. 여러 클래스를 확장해야하는 경우 인터페이스 여야합니다. 당신은 이것을 할 수 있습니다 :
public class ImplementingClass extends AbstractClass implements InterfaceA, InterfaceB
{
... // implementation
}
인터페이스 예는 다음과 같습니다.
interface InterfaceA
{
void interfaceMethod();
}
이것은 기본적으로 다음과 같습니다.
abstract public class InterfaceA
{
abstract public void interfaceMethod();
}
유일한 차이점은 두 번째 방법은 컴파일러가 실제로 인터페이스라는 것을 알리지 않는다는 것입니다. 사람들이 인터페이스 만 구현하고 다른 인터페이스는 구현하지 않으려는 경우에 유용 할 수 있습니다. 그러나 일반적인 초급 규칙으로 추상 클래스에 추상 메소드 만있는 경우 인터페이스로 만들어야합니다.
다음은 불법입니다 :
interface InterfaceB
{
void interfaceMethod() { System.out.print("ERROR!"); }
}
인터페이스에서 메소드를 구현할 수 없습니다. 이것은 두 개의 다른 인터페이스를 구현하면 해당 인터페이스의 다른 메소드가 충돌 할 수 없음을 의미합니다. 인터페이스의 모든 메소드는 추상이므로 메소드를 구현해야하며 메소드가 상속 트리에서 유일한 구현이므로 컴파일러는 메소드를 사용해야한다는 것을 알고 있습니다.
c.implementedMethod()
"Overriden!"을 인쇄합니까? SecondImplementingClass
무시하지 않습니다 implementedMethod()
.
Java 클래스는 다음과 같은 조건에서 요약됩니다.
1. 방법 중 하나 이상이 추상으로 표시됩니다.
public abstract void myMethod()
이 경우 컴파일러는 전체 클래스를 추상으로 표시하도록합니다.
2. 수업은 초록으로 표시됩니다.
abstract class MyClass
이미 말했듯이 : 추상 메소드가있는 경우 컴파일러는 전체 클래스를 추상으로 표시하도록 강제합니다. 그러나 추상 메서드가 없더라도 클래스를 추상으로 표시 할 수 있습니다.
일반적인 사용 :
추상 클래스의 일반적인 사용은 인터페이스와 유사한 클래스의 개요를 제공하는 것입니다. 그러나 인터페이스와 달리 이미 기능을 제공 할 수 있습니다. 즉, 클래스의 일부 부분이 구현되고 일부 부분은 메소드 선언으로 간략하게 설명됩니다. ("요약")
추상 클래스는 인스턴스화 할 수 없지만 추상 클래스를 기반으로 구체적인 클래스를 생성 한 다음 인스턴스화 할 수 있습니다. 그렇게하려면 추상 클래스에서 상속하고 추상 메서드를 재정의해야합니다 (예 : 구현).
abstract
클래스가 추상적이려면 키워드 만 있으면 된다는 것이 확실합니다 . 그러나 구체적인 클래스 는 메소드를 포함 할 수 없습니다 . 따라서 클래스에 메소드 가 있으면 컴파일러에 클래스로 선언 해야합니다. abstract
abstract
abstract
abstract 키워드를 사용하여 선언 된 클래스 는로 알려져 있습니다 abstract class
. 추상화는 데이터 구현 세부 사항을 숨기고 사용자에게 기능 만 표시하는 프로세스입니다. 추상화를 사용하면 객체가 수행하는 방식 대신 객체가 수행하는 작업에 집중할 수 있습니다.
추상 클래스의 주요 사항
추상 클래스는 추상 메서드를 포함하거나 포함하지 않을 수 있습니다. 추상 클래스가 아닐 수 있습니다.
추상 메소드는 다음과 같이 구현없이 (중괄호없이 세미콜론으로) 선언 된 메소드입니다.
예 : abstract void moveTo(double deltaX, double deltaY);
클래스에 추상 메소드가 하나 이상 있으면 해당 클래스는 추상적이어야합니다.
추상 클래스가 인스턴스화되지 않을 수 있습니다 (Abstract 클래스의 객체를 생성 할 수 없음)
추상 클래스를 사용하려면 다른 클래스에서 상속해야합니다. 모든 추상 메소드에 구현을 제공하십시오.
추상 클래스를 상속하면 모든 추상 메소드에 구현을 제공해야합니다.
추상 클래스abstract
선언 선언하는 동안 클래스 앞에 키워드를
지정 하면 추상이됩니다. 아래 코드를 살펴보십시오.
abstract class AbstractDemo{ }
추상 메서드abstract
선언 선언하는 동안 메서드 앞에 키워드를
지정 하면 추상이됩니다. 아래 코드를 살펴보십시오.
abstract void moveTo();//no body
수업을 추상화해야하는 이유
객체 지향 도면 응용 프로그램에서 원, 사각형, 선, 베 지어 곡선 및 기타 여러 그래픽 객체를 그릴 수 있습니다. 이러한 객체에는 모두 특정 상태 (예 : 위치, 방향, 선 색상, 채우기 색상)와 동작 (예 :-: 이동 위치, 회전, 크기 조정, 그리기)이 공통적으로 있습니다. 이러한 상태와 동작 중 일부는 모든 그래픽 객체에서 동일합니다 (예 : 채우기 색상, 위치 및 이동 위치). 다른 것들은 다른 구현이 필요합니다 (예 : 크기 조정 또는 그리기). 모든 그래픽 객체는 스스로 그림을 그리거나 크기를 조정할 수 있어야하며, 작동 방식이 다릅니다.
이것은 추상 슈퍼 클래스에게 완벽한 상황입니다. 유사성을 활용 GraphicObject
하고 다음 그림과 같이 동일한 추상 부모 개체 (예 : :)에서 상속하도록 모든 그래픽 개체를 선언 할 수 있습니다 .
먼저, GraphicObject
현재 위치 및 moveTo 메소드와 같은 모든 서브 클래스가 완전히 공유하는 멤버 변수 및 메소드를 제공하기 위해 추상 클래스를 선언합니다 . GraphicObject
또한 모든 서브 클래스에 의해 구현되어야하지만 다른 방식으로 구현되어야하는 draw 또는 resize와 같은 추상 메소드를 선언했습니다. GraphicObject
클래스는 다음과 같이 볼 수 있습니다 :
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();
}
서브 클래스에서의 추상 메소드 사용 and와 GraphicObject
같은
각각의 추상이 아닌 서브 클래스 는 and 메소드에 대한 구현을 제공해야합니다 .Circle
Rectangle
draw
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
}
}
main
메소드 내부에서 다음과 같은 모든 메소드를 호출 할 수 있습니다.
public static void main(String args[]){
GraphicObject c = new Circle();
c.draw();
c.resize();
c.moveTo(4,5);
}
Java에서 추상화를 달성하는 방법
자바에서 추상화를 얻는 두 가지 방법이 있습니다
생성자, 데이터 멤버, 메소드 등이있는 추상 클래스
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);
}
}
산출:
GraphicObject is created
Draw the Circle
Change position according to 6 and 4
두 가지 규칙을 기억하십시오.
클래스에 추상 메소드와 구체적인 메소드가 거의없는 경우 클래스로 선언하십시오 abstract
.
클래스에 추상 메소드 만있는 경우이를로 선언하십시오 interface
.
참고 문헌 :
간단히 말해서, 추상 클래스는 약간 더 많은 기능을 가진 인터페이스처럼 생각할 수 있습니다.
추상 클래스를위한 인터페이스도 인스턴스화 할 수 없습니다.
인터페이스에서 메소드 헤더를 정의하면 모든 구현자가 강제 로 모든 헤더 를 구현 해야 합니다. 추상 클래스에서 메소드 헤더를 정의 할 수도 있지만 여기서는 인터페이스의 차이점에 따라 메소드의 본문 (일반적으로 기본 구현)을 정의 할 수도 있습니다. 또한 다른 클래스가 추상 클래스를 확장 (구현하지 않고 따라서 자식 클래스 당 하나의 추상 클래스 만 가질 수 있음 ) 할 때 추상 메소드 를 지정하지 않는 한 추상 클래스의 모든 메소드를 강제로 구현하지는 않습니다 ( 이 경우 인터페이스와 같이 작동하며 메소드 본문을 정의 할 수 없습니다).
public abstract class MyAbstractClass{
public abstract void DoSomething();
}
그렇지 않은 경우 추상 클래스의 일반 메서드의 경우 "상속자"는 기본 동작을 사용하거나 평소처럼 재정의 할 수 있습니다.
예:
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();
}
오라클 문서에서
추상 방법 및 클래스 :
추상 클래스는 추상으로 선언 된 클래스이며 추상 메소드를 포함하거나 포함하지 않을 수 있습니다.
추상 클래스는 인스턴스화 할 수 없지만 서브 클래스 화는 가능합니다
추상 메소드는 다음과 같이 구현없이 (중괄호없이 세미콜론으로) 선언 된 메소드입니다 .
abstract void moveTo(double deltaX, double deltaY);
클래스에 추상 메소드가 포함 된 경우 클래스 자체는 다음과 같이 추상으로 선언되어야합니다.
public abstract class GraphicObject {
// declare fields
// declare nonabstract methods
abstract void draw();
}
추상 클래스가 서브 클래 싱 될 때, 서브 클래스는 일반적으로 부모 클래스의 모든 추상 메소드에 대한 구현을 제공합니다. 그러나 그렇지 않은 경우 서브 클래스도 abstract로 선언해야합니다. .
이후 abstract classes
및interfaces
관련, SE 질문 아래를 보라 :
여기에 답을 얻으십시오.
BTW-최근 질문 한 내용입니다. 명성을 쌓기위한 새로운 질문에 대해 생각해보십시오.
편집하다:
이 포스터와 참조 된 질문의 이름은 같거나 최소한 비슷한 이름이지만 user-id는 항상 다릅니다. 따라서 기술적 인 문제가 있습니다. keyur가 다시 로그인하는 데 문제가 있고 그의 질문에 대한 답을 찾는 데 어려움이 있거나 SO 커뮤니티를 즐겁게하는 일종의 게임입니다.)
추상 클래스는 직접 인스턴스화 할 수 없지만 사용할 수 있도록 파생되어야합니다. 클래스는 반드시 이 추상 메소드를 포함하는 경우 추상적 일 : 직접
abstract class Foo {
abstract void someMethod();
}
또는 간접적으로
interface IFoo {
void someMethod();
}
abstract class Foo2 implements IFoo {
}
그러나 추상 메소드를 포함하지 않고 클래스는 추상 일 수 있습니다. 직접 인스턴스화를 방지하는 방법, 예 :
abstract class Foo3 {
}
class Bar extends Foo3 {
}
Foo3 myVar = new Foo3(); // illegal! class is abstract
Foo3 myVar = new Bar(); // allowed!
후자의 스타일의 추상 클래스는 "인터페이스 유사"클래스를 작성하는 데 사용될 수 있습니다. 인터페이스와 달리 추상 클래스에는 비추 상 메소드와 인스턴스 변수가 포함될 수 있습니다. 이를 사용하여 클래스 확장에 대한 몇 가지 기본 기능을 제공 할 수 있습니다.
또 다른 빈번한 패턴은 추상 클래스에서 주요 기능을 구현하고 확장 클래스로 구현할 추상 방법으로 알고리즘의 일부를 정의하는 것입니다. 어리석은 예 :
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();
}
추상 클래스는 추상으로 선언 된 클래스이며 추상 메서드를 포함하거나 포함하지 않을 수 있습니다. 추상 클래스는 인스턴스화 할 수 없지만 서브 클래스화할 수 있습니다.
즉, abstract 키워드로 선언 된 클래스를 java에서 abstract 클래스라고합니다. 추상 (본문없는 방법) 및 비 추상적 방법 (본문이있는 방법)을 가질 수 있습니다.
중요 사항 :- 추상 클래스는 객체를 인스턴스화하는 데 사용할 수 없으며 객체 참조를 만드는 데 사용할 수 있습니다. Java의 런타임 다형성에 대한 접근 방식은 수퍼 클래스 참조를 사용하여 구현되기 때문입니다. 따라서 서브 클래스 객체를 가리키는 데 사용할 수 있도록 추상 클래스에 대한 참조를 만들 수 있어야합니다. 아래 예제에서이 기능을 볼 수 있습니다
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();
}
}
추상 클래스는 완전히 구현되지 않았지만 서브 클래스에 대한 청사진을 제공하는 클래스입니다. 완전히 정의 된 구체적인 메소드를 포함하여 부분적으로 구현 될 수도 있지만 추상 메소드를 보유 할 수도 있습니다. 서명은 있지만 메소드 본문은없는 메소드입니다. 모든 서브 클래스는 각 추상 메소드에 대한 본문을 정의해야하며, 그렇지 않으면 추상으로 선언되어야합니다. 추상 클래스는 인스턴스화 할 수 없기 때문에 활용하려면 적어도 하나의 서브 클래스로 확장해야합니다. 추상 클래스를 일반 클래스로 생각하면 하위 클래스가 누락 된 정보를 채 웁니다.