سؤال

لنفترض لدي فئة أساسية B، وفئة مشتقة D. أتمنى أن يكون فو () طريقة في الفئة الأساسية بلدي ترجع كائن جديد من أي نوع كان المثيل. لذلك، على سبيل المثال، إذا كنت استدعاء B.foo () فإنها ترجع كائن من نوع B، في حين إذا أدعو D.foo () فإنها ترجع كائن من نوع D. وفي الوقت نفسه، تنفيذ يقيم فقط في الفئة الأساسية B.

هل هذا ممكن؟

هل كانت مفيدة؟

المحلول

ولا. جعل "فو" طريقة مجردة.

abstract class B {
    public abstract B foo();
}

وأو تتلقى مصنع مجردة من خلال منشئ الفئة الأساسية:

abstract class B {
    private final BFactory factory;
    protected B(BFactory factory) {
        this.factory = factory;
    }
    public B foo() {
        return factory.create();
    }
}
interface BFactory {
    B create();
}

إضافة أنواع الإرجاع التغاير والأدوية لتذوق.

نصائح أخرى

وطالما كل فئة لديها منشئ افتراضي:

    public B instance() throws Exception {
        return getClass().newInstance();
    }

حسنا، أنا يمكن أن يكون خارج ولكن أود أن نفترض أنه منذ "هذا" يشير دائما إلى كائن الحالي، هل يمكن أن تفعل شيئا من هذا القبيل

public B foo() {
    return this.getClass().newInstance();
}

وأو شيء من هذا القبيل؟ إذا قمت بإنشاء مثيل D ومن ثم استدعاء d.foo () يجب أن تحصل على إرجاع مثيل D كما B. هل يمكن إعادته ككائن عادي ولكن يجب أن تكون محددة قدر الإمكان في هذه الحالة، على ما أعتقد.

وبصرف النظر عن حقيقة أن أعتقد أن هناك ربما هو خلل في التصميم إذا كنت ترغب في تحقيق ذلك، قد تتمكن من محاولة النهج التالي.

في سؤالك، كنت تستخدم ثابت (الفئة) طرق، B.foo ()، D.foo ()، وهذا لا يمكن تحقيقه باستخدام الميراث لأن أساليب ثابتة لم يكن لديك الطبيعة الديناميكية، فإنها لا يشاركون في نظام البحث. لذلك لم يكن لديك ما يكفي من معلومات نوع.

إذا كنت تستخدم فو دالة عضو () هل يمكن أن يكون بناء التالي:

public class B {
    public B foo()
    throws IllegalAccessException, InstantiationException {
        return this.getClass().newInstance();
    }
}

public class D  extends B{    
}

public class Test {
    public static final void main(String[] args)
    {
        try {
            System.out.println((new B()).foo());
            System.out.println((new D()).foo());
        } catch (IllegalAccessException e) {
            e.printStackTrace();  
        } catch (InstantiationException e) {
            e.printStackTrace();  
        }
    }
}

وكما يقول إجابات أخرى، يمكنك استخدام getClass () عبارة. newInstance () إذا كان هناك منشئ عدم الحجة في كل فئة فرعية (تأكد للقبض InstantiationException وIllegalAccessException).

وإذا كان أي من المنشئات تتطلب الوسائط، يمكنك إما استخدام انعكاس أو (الأفضل من وجهة نظري) تحديد طريقة مثل getNewInstance () الذي يمكنك تجاوز في فئة فرعية فقط إذا لزم الأمر.

ومنها مثلا.

Thing foo() {
    Thing th = getNewInstance();
    // do some stuff with th
    return th;
}

Thing getNewInstance() {
    return getClass().newInstance();
}

وبعد ذلك getNewInstance () يمكن تجاوز إلا إذا كنت حقا بحاجة إلى ذلك، لفرعية التي ليس لديها منشئ افتراضي.

Thing getNewInstance() {
    return new BigThing(10, ThingSize.METRES);
}

وأعتقد أن هذا قد يكون من الممكن القيام باستخدام الانعكاس، أي في الطبقة المتفوقة الخاص لديك:

public ClassName getFoo() throws InstantiationException, IllegalAccessException
{
    return getClass().newInstance();
}

وأين اسم_الفئة هو اسم الفئة الأساسية الخاصة بك.

وسيكون لديك للادلاء أينما تريد استخدامه على الرغم من ... أنا لست متأكد من أن هذا هو حقا حلا رائعا!

تعديل: newInstance () اكتب أساليب وعادة ما تكون ثابتة، وبالطبع سوف لا يكون لديك فكرة عن ما نوع فرعية الخاص بك هو مع أسلوب ثابت

وأنا لا أعتقد أن هناك أي طريقة للحصول على ثابت طريقة ل(حيوي) إنشاء مثيل من فئة فرعية.

وRik

حسنا، المشكلة الحقيقية هي أن لدي مجرد شيء الفئة الأساسية. والشيء لديه طريقة تسمى getNextThing () التي ترجع مثيل جديد من شيء.

وبعد ذلك، لدي عدد من الفئات الفرعية مثل BigThing، LittleThing، SomethingThing، وأنا لا أريد أن تبقي إعادة صياغة طريقة getNextThing () لكل منهم. ويبدو الإسراف، لأنها جميعا أن نفعل نفس الشيء ....

وأنا غير صحيحة في وجهة نظري؟

وأنا لست متأكدا لماذا تحاول أن تفعل ما نحاول القيام به فعلا. توفير أكثر من سياق قد دعونا نقدم لكم مزيد من المساعدة.

public class B <X extends B>{

public X foo() throws InstantiationException, IllegalAccessException{
    return (X)this.getClass().newInstance();
}
}        
public class C extends B<C>{        

}

واسمحوا لي أن أقدم لكم هذه النصيحة. الطريق الطبقات CS تميل إلى أن تدرس هي أن الأساتذة هم الافتتان مع الميراث، ولكن لم ترد على تكوينها. وأعتقد أن ما كنت قد تبحث عن تكوينها. وذلك بدلا من استدعاء getNextThing على الشيء نفسه، ربما يجب أن نفكر في جعل الشيء تنفيذ <وأ href = "http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Iterable.html "يختلط =" noreferrer نوفولو "> Iterable

وهذا يعني أنك سوف تحتاج فقط لكتابة <لأ href = "http://java.sun.com/j2se/1.5.0/docs/api/java/util/Iterator.html" يختلط = "نوفولو noreferrer "> مكرر التي يمكن أن تلخص منطق الحصول على الشيء التالي، كما أنه لا يبدو أن تنسجم مع نموذج ميراثك. ميزة أخرى لهذا هو أن تحصل بعض الأجهزة النحوية لطيفة للخروج من هذا (معززة لفهم حلقة).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top