2012-01-02 3 views
4

я действительно читал книгу о шаблонах проектирования в Java, и я новичок :)отбрасывается в абстрактный класс ... как это возможно?

http://www.amazon.com/Design-Patterns-Java-TM-Software/dp/0321333020/ в главе о композитном рисунке я наткнулся на коде, который озадачивает меня, преобразованный в абстрактный класс, у меня тоже не совсем понятно, что происходит, когда подкласса вызывает конструктор абстрактного суперкласса, можете ли вы мне помочь!

литые, что я говорю о том, в isTree (Set посетил)

 MachineComponent c = (MachineComponent) i.next(); 
     if (visited.contains(c) || !c.isTree(visited)) 

Как мы можем назвать isTree метод подкласса после броска к его абстрактному суперклассу в то время как isTree метод суперкласса является Абстрактные?

Вот отрывки из двух классов:

package com.oozinoz.machine; 
/* 
* Copyright (c) 2001, 2005. Steven J. Metsker. 
*/ 

import java.util.*; 
import com.oozinoz.iterator.ComponentIterator; 

/** 
* Objects of this class represent either individual machines or composites of 
* machines. 
*/ 

public abstract class MachineComponent { 

    /* 
    * Subclasses implement this to support the isTree() algorithm. 
    */ 

    protected abstract boolean isTree(Set s); 

    // rest of class omitted 
} 

2:

package com.oozinoz.machine;  
/* 
* Copyright (c) 2001, 2005. Steven J. Metsker. 
*/ 

import java.util.*; 
import com.oozinoz.iterator.ComponentIterator; 
import com.oozinoz.iterator.CompositeIterator; 

/** 
* Represent a collection of machines: a manufacturing line, a bay, or a 
* factory. 
*/ 

public class MachineComposite extends MachineComponent { 
    protected List components = new ArrayList(); 

    /** 
    * @param visited a set of visited nodes 
    * @return true if this composite is a tree 
    * @see MachineComponent#isTree() 
    */ 

    protected boolean isTree(Set visited) { 
     visited.add(this); 
     Iterator i = components.iterator(); 
     while (i.hasNext()) { 
      MachineComponent c = (MachineComponent) i.next(); 
      if (visited.contains(c) || !c.isTree(visited)) 
       return false; 
     } 
     return true; 
    } 

    // rest of class omitted 
} 
+1

Пожалуйста форматировать Ваш код правильно, если вы собираетесь просто сбросить целые файлы в –

ответ

8

Это различие между типом времени выполнения (фактическим типом) и типом времени компиляции.

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

Класс MachineComponent - это тип времени компиляции назначенной переменной. Но фактический экземпляр (или может быть) создан с этим абстрактным классом.

+2

@ wrscheider99 - Абсолютно правильно. И на самом деле это ОПРЕДЕЛЕНИЕ абстрактного класса - это класс, для которого вы не можете создавать какие-либо конкретные экземпляры, для которых вы ДОЛЖНЫ подкласс в ORDER создать конкретный экземпляр. Честно говоря, «интерфейсы», как правило, намного полезнее на Java. Но абстрактные классы * важны во многих случаях, включая пример OP. – paulsm4

1

Q: Можете ли вы бросить на абстрактный класс?

A: Конечно, вы можете.

Что вы не может do является абстрактным методом абстрактного класса. (вставка из секции комментариев - Andrew Barber - ниже). Фактически вы вызываете конкретную реализацию этого в подклассе.

+6

Да ... полностью не правда. – mre

+2

@mre, что не так? Абстрактный метод не имеет кода, так что бы вы звонили? – Paul

+1

Это правда, хотя я могу видеть, как некоторые могут не думать об этом, если они заимствуют термины по-другому, чем ответчик. Если вы считаете, что вызываете абстрактную функцию, вы на самом деле вызываете ее конкретную реализацию в подклассе. –

2

Хорошо, давайте возьмем Cat, который является подклассом абстрактного класса Animal.

Вы можете отличить Cat в Animal, потому что кошка является животным. Он делает все, что делает нормальное животное, так как оно имеет функции животного.

Подклассификация абстрактного класса такая же. Вы можете просто использовать «это», потому что это подкласс.

Вы можете определить список животных как зоопарк, но у него могут быть собаки и кошки - в конце концов, они оба животные.

Кастинг Cat Ань Animal на самом деле не делает его менее Cat, чем это было - вы просто сказать код, чтобы рассматривать его, как он будет относиться к любым другим животным.

Редактировать
В случае, если Вы не любите кошек (я не либо), позвольте мне перенаправить вас на Wikipedia article about inheritance. Абстрактные классы были бы бесполезны, если вы не можете их бросить.

4

isTree является абстрактным только для абстрактного класса. Как только класс был инициализирован как не абстрактный, отбрасывание его на абстрактный не изменит его память. Поэтому вызов метода в абстрактном классе эффективно называет его конкретной реализацией.

Причина, по которой это полезно, заключается в передаче подклассов через абстрактную реализацию.

Скажем, класс String имеет метод «длины». Нет необходимости иметь функцию для каждого возможного подкласса типа String. Вместо этого вы передаете основную (абстрактную) строку, которая имеет реализацию «длина», и передайте ее.

3

ОК - давайте попробуем еще раз:

Q: Можете ли вы бросить на абстрактный класс?

: Конечно - конечно, вы можете

. Например:

public class UseAbstract 
{ 
    public static void main (String[] args) 
    { 
    // Instantiate an abstract class 
    AbstractPet myDog = new Dog(); 
    myDog.sound(); 

    // Instantiate a concrete class 
    Cat myCat = new Cat(); 
    myCat.sound(); 

    // Cast a concrete class to an abstract class 
    AbstractPet somePet = (AbstractPet)myCat; 
    somePet.sound(); 
    } 
} 

abstract class AbstractPet 
{ 
    void sound() 
    { 
    System.out.println ("eek"); 
    } 
} 

class Dog extends AbstractPet 
{ 
    void sound() 
    { 
    System.out.println ("Woof"); 
    } 
} 

class Cat extends AbstractPet 
{ 
    void sound() 
    { 
    System.out.println ("meow"); 
    } 
}