2013-07-06 22 views
7

istnieją następujące zajęcia:Java „abstrakcyjne jak” metoda z ciałem

public abstract class Super 
{ 
    public abstract void run(); 
} 

public class Sub1 extends Super 
{ 
    @Override 
    public void run() 
    { 
     System.out.println("Method called"); 
     System.out.println("Sub1 called"); 
    } 
} 

public class Sub2 extends Super 
{ 
    @Override 
    public void run() 
    { 
     System.out.println("Method called"); 
     System.out.println("Sub2 called"); 
    } 
} 

jak mogę uniknąć, że muszę napisać „System.out.println (” Metoda zwana „);” dwa razy?

Dziękuję za odpowiedzi

CalibeR.50

+1

Jeśli każda implementacja jest taka sama, dlaczego wyodrębnia się tę metodę. – NINCOMPOOP

+0

Czy możesz nam pokazać, jak wywoływana jest metoda 'run()'? –

+0

to tylko przykład, będzie więcej kodu w metodach uruchamiania w Sub1 i Sub2. –

Odpowiedz

12

Wprowadzić wspólną funkcjonalność do nadklasy i zdefiniować inną abstrakcyjną metodę, dla której podklasy będą definiować własną implementację.

public abstract class Super { 
    public void run() { 
     System.out.println("Method called"); 
     printMessage(); 
    } 
    abstract void printMessage(); 
} 

public class Sub1 extends Super { 
    @Override 
    void printMessage() { 
     System.out.println("Sub1 called"); 
    } 
} 

public class Sub2 extends Super { 
    @Override 
    void printMessage() { 
     System.out.println("Sub2 called"); 
    } 
} 

W ten sposób można uniknąć podwójnego wywoływania wspólnej metody nadklasy.

+0

Ale nie jestem w stanie uczynić metody "printMessage" prywatnym. Czy w twoim przykładzie możliwe jest tylko wywoływanie opcji "uruchom"? –

+0

@ CalibeR.50 Jeśli jest prywatny, nie będzie dostępny z poziomu nadklasy. Możesz jednak uczynić go * pakietem prywatnym *, pomijając modyfikator poziomu dostępu, i będzie widoczny tylko w pakiecie – user000001

+2

O, zapomniałem o ochronie. Spróbuję, jeśli to zadziała w moim przypadku. Dziękujemy –

1

Jeśli chcesz wszystkie podklasy mają identyczny problem, wtedy prawidłowa technika byłoby zakodować metody tylko w nadrzędnej, pozwalając podklasy, aby ją odziedziczyć . Ale to wyeliminowałoby potrzebę, aby twoja superklasa była abstrakcyjna w tym przypadku, ponieważ zastosuje ona swoją jedyną metodę.

+0

Wyjaśnię trochę przykład, aby wyjaśnić, co próbuję zrobić, –

4

Można umieścić run() wdrażanie do klasy abstrakcyjnej:

// Super is still an abstract class 
public abstract class Super 
{ 
    // While method run is not an abstract method: 
    public void run() 
    { 
     System.out.println("Method called"); 
    } 
} 

public class Sub1 extends Super 
{ 
    // There's no need of declaring run() here unless you want to change its behaviour 
} 

public class Sub2 extends Super 
{ 
} 

W edytowanej wersji swoje pytanie, możesz po prostu użyć odziedziczony realizację run

// Super is still abstract 
public abstract class Super 
{ 
    // But method run is not abstract 
    public void run() 
    { 
     System.out.println("Method called"); 
    } 
} 

public class Sub1 extends Super 
{ 
    @Override 
    public void run() 
    { 
     super.run(); // <- call Super.run() that prints "Method called" 
     System.out.println("Sub1 called"); 
    } 
} 

public class Sub2 extends Super 
{ 
    @Override 
    public void run() 
    { 
     super.run(); 
     System.out.println("Sub2 called"); 
    } 
} 
+0

Edytowałem moje pytanie, aby wyjaśnić, co próbuję zrobić dokładnie –

+0

, musisz również wywołać super.run(), jeśli zdecydujesz się to zmienić metoda w Sub1 i Sub2 – veritas

+0

@ CalibeR.50 Edytowałem moją odpowiedź –

2

można umieścić wspólny kod w metodzie super klasy i wywołaj go metodami podklasowymi.

public abstract class Super 
{ 
    public abstract void run(); 
    // code common to both the sub classes implemented 
    public void print() { 
    System.out.println("Method called"); 
    } 
} 

public class Sub1 extends Super 
{ 
    @Override 
    public void run() 
    { 
    print(); 
    System.out.println("Sub1 called"); 
    // sub class specific code here 
    } 
} 

public class Sub2 extends Super 
{ 
    @Override 
    public void run() 
    { 
     print(); 
     System.out.println("Sub2 called"); 
     // sub class specific code here 
    } 
} 
+0

Tak, to by działało. Ale czy nie ma możliwości wymuszenia, aby kod był wykonywany z "run"? –

2

Użyj "metoda szablonowa":

public class Super 
{ 
    public void template() { 
     System.out.println("Method called"); 
     run(); 
    } 

    public abstract void run(); 
} 

public class Sub1 extends Super 
{ 
    @Override 
    public void run() // out called before run 
    { 

    } 
} 

public class Sub2 extends Super 
{ 
    @Override 
    public void run() // out called before run 
    { 

    } 
} 

Aditionally można dokonać chroniony run.

3

Jeśli część implementacji run() jest wspólna dla Sub1 i Sub2, proponuję po prostu użyć dziedziczenia i obejścia w podklasach. Oto przykładowy kod:

public abstract class Super 
{ 
    public void run() { 
     // Code shared by all subclasses 
     System.out.println("Method called"); 
    } 

} 

public class Sub1 extends Super 
{ 
    @Override 
    public void run() 
    { 
     super.run(); 
     System.out.println("Sub1 called"); 
    } 
} 

public class Sub2 extends Super 
{ 
    @Override 
    public void run() 
    { 
     super.run(); 
     System.out.println("Sub2 called"); 
    } 
} 

Sztuką jest to, że klasa Super można zdefiniować abstract podczas wdrażania metod. Jeśli masz podklasy, które nie potrzebują wspólnego kodu, możesz zastąpić run() bez kodu super.run() i zmienić to wszystko.