منصة - هل تدعم Java قيم المعلمات الافتراضية؟




مميزات لغة الجافا (13)

جئت عبر بعض كود جافا الذي كان يحتوي على البنية التالية:

public MyParameterizedFunction(String param1, int param2)
{
    this(param1, param2, false);
}

public MyParameterizedFunction(String param1, int param2, boolean param3)
{
    //use all three parameters here
}

وأنا أعلم أنه في C ++ يمكنني تعيين معلمة قيمة افتراضية. فمثلا:

void MyParameterizedFunction(String param1, int param2, bool param3=false);

هل تدعم Java هذا النوع من البنية؟ هل هناك أي أسباب وراء تفضيل بناء الجملة المكون من خطوتين؟


أسلوب مماثل لـ https://.com/a/13864910/2323964 الذي يعمل في Java 8 هو استخدام واجهة باستخدام برنامج getters الافتراضي. سيكون هذا أكثر مطولاً في الفراغات البيضاء ، لكنه قابل للتهكم ، وهو أمر رائع عندما يكون لديك مجموعة من الحالات التي تريد فيها بالفعل جذب الانتباه إلى المعلمات.

public class Foo() {
    public interface Parameters {
        String getRequired();
        default int getOptionalInt(){ return 23; }
        default String getOptionalString(){ return "Skidoo"; }
    }

    public Foo(Parameters parameters){
        //...
    }

    public static void baz() {
        final Foo foo = new Foo(new Person() {
            @Override public String getRequired(){ return "blahblahblah"; }
            @Override public int getOptionalInt(){ return 43; }
        });
    }
}

جرب هذا الحل:

public int getScore(int score, Integer... bonus)
{
    if(bonus.length > 0)
    {
        return score + bonus[0];
    }

    return score;
}

قد أكون واضحًا هنا ، لكن لماذا لا تقوم ببساطة بتطبيق المعلمة "الافتراضية" بنفسك؟

public class Foo() {
        public void func(String s){
                func(s, true);
        }
        public void func(String s, boolean b){
                //your code here
        }
}

الافتراضي الذي تستخدمه الأثير

func ("سلسلتي") ؛

وإذا كنت لا ترغب في استخدام الافتراضي ، قد تستخدم

func ("my string"، false)؛


كما ذكر سكالا ، ومن الجدير بالذكر أيضا Kotlin . في معلمات الدالة Kotlin يمكن أن تحتوي على قيم افتراضية أيضًا ، بل ويمكنها أيضًا الرجوع إلى معلمات أخرى:

fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size) {
    ...
}

مثل Scala ، يعمل Kotlin على JVM ويمكن دمجه بسهولة في مشاريع Java الحالية.


لا ، ولكن لدينا بديل في شكل التحميل الزائد للوظيفة.

دعا عندما لا يتم تمرير المعلمة

void operation(){

int a = 0;
int b = 0;

} 

دعا عندما تم تمرير المعلمة "أ"

void operation(int a){

int b = 0;
//code

} 

دعا عندما مرت المعلمة ب

void operation(int a , int b){
//code
} 

لا ، ولكن يمكنك استخدام Pattern Builder Pattern ، كما هو موضح في إجابة هذه .

كما هو موضح في الإجابة المرتبطة ، يتيح لك نمط الباني كتابة الكود مثل

Student s1 = new StudentBuilder().name("Eli").buildStudent();
Student s2 = new StudentBuilder()
                 .name("Spicoli")
                 .age(16)
                 .motto("Aloha, Mr Hand")
                 .buildStudent();

حيث يمكن أن تحتوي بعض الحقول على قيم افتراضية أو تكون اختيارية.


لا.

يمكنك تحقيق نفس السلوك عن طريق تمرير كائن له إعدادات افتراضية ذكية. ولكن مرة أخرى ، يعتمد الأمر على قضيتك.


لا. بشكل عام لا يحتوي جافا على الكثير من السكر النحوي ، حيث أنهم حاولوا جعل لغة بسيطة.


للأسف نعم.

void MyParameterizedFunction(String param1, int param2, bool param3=false) {}

يمكن كتابتها في Java 1.5 على النحو التالي:

void MyParameterizedFunction(String param1, int param2, Boolean... params) {
    assert params.length <= 1;
    bool param3 = params.length > 0 ? params[0].booleanValue() : false;
}

لكن أم لا يجب أن تعتمد على شعورك حول المجمع الذي يولد a

new Boolean[]{}

لكل مكالمة.

لمعلمات متعددة قابلة للتطبيق:

void MyParameterizedFunction(String param1, int param2, bool param3=false, int param4=42) {}

يمكن كتابتها في Java 1.5 على النحو التالي:

void MyParameterizedFunction(String param1, int param2, Object... p) {
    int l = p.length;
    assert l <= 2;
    assert l < 1 || Boolean.class.isInstance(p[0]);
    assert l < 2 || Integer.class.isInstance(p[1]);
    bool param3 = l > 0 && p[0] != null ? ((Boolean)p[0]).booleanValue() : false;
    int param4 = l > 1 && p[1] != null ? ((Integer)p[1]).intValue() : 42;
}

هذا يطابق بناء الجملة C ++ ، والذي يسمح فقط للمعلمات الافتراضية في نهاية قائمة المعلمات.

ما وراء بناء الجملة ، هناك اختلاف حيث تم تشغيل هذا النوع من التحقق من المعلمات الافتراضية التي تم تمريرها ونوع C ++ يتحقق منها أثناء التحويل البرمجي.


هذه هي الطريقة التي قمت بها ... ليس من الملائم ربما أن يكون لديك "حجة اختيارية" ضد المعلمة المحددة الخاصة بك ، ولكنها تؤدي المهمة بنجاح:

public void postUserMessage(String s,boolean wipeClean)
{
    if(wipeClean)
    {
        userInformation.setText(s + "\n");
    }
    else
    {
        postUserMessage(s);
    }
}

public void postUserMessage(String s)
{
    userInformation.appendText(s + "\n");
}

ملاحظة: يمكنني استدعاء نفس اسم الأسلوب إما بسلسلة أو يمكنني استدعائه بسلسلة وقيمة منطقية. في هذه الحالة ، سيؤدي الإعداد "مسح بتنظيف" إلى "True" إلى استبدال كل النص في TextArea باستخدام السلسلة المتوفرة. تعيين المسححطئة إلى false أو تركها كلها معًا ببساطة يضيف النص المقدم إلى TextArea.

لاحظ أيضًا أنني لا أكرر الشفرة في الطريقتين ، فأنا أقوم فقط بإضافة وظيفة القدرة على إعادة ضبط TextArea من خلال إنشاء طريقة جديدة بالاسم نفسه فقط مع القيمة المنطقية المضافة.

أعتقد بالفعل أن هذا منظف قليلاً مما لو قدمت Java "حجة اختيارية" لمعلماتنا حيث أننا سنحتاج إلى رمز للقيم الافتراضية إلخ. في هذا المثال ، لا داعي للقلق بشأن أي من ذلك. نعم ، لقد أضفت طريقة أخرى إلى صفي ، ولكن من السهل قراءتها على المدى الطويل في رأيي المتواضع.


هناك نصف دزينة أو قضايا أفضل مثل هذا ، في نهاية المطاف تصل إلى نمط مصنع ثابت ... انظر api التشفير لهذا. فرز يصعب تفسيره ، لكن فكر فيه بهذه الطريقة: إذا كان لديك منشئ ، افتراضي أو غير ذلك ، فإن الطريقة الوحيدة لنشر الحالة خارج الأقواس المتعرجة هي إما أن تكون منطقية isValid ؛ (مع القيمة الفارغة كقيمة افتراضية v منشئ فاشل) أو رمي استثناء لا يعد مفيدًا عند إعادته من المستخدمين الميدانيين.

يجب أن يكون ملعون قانون تصحيح ، وأنا أكتب ألف الصانعين الخط وتفعل ما أحتاج. أجد استخدام isValid في بناء الكائن - وبعبارة أخرى ، اثنين من صانعي الخط - ولكن لسبب ما أنا أهاجر إلى نمط مصنع ثابت. أنا فقط يبدو أنك تستطيع أن تفعل الكثير إذا كنت في مكالمة طريقة ، لا تزال هناك مشاكل متزامنة () ولكن يمكن أن يكون 'الافتراضي' أفضل (أكثر أماناً)

أعتقد أن ما نحتاج إلى القيام به هنا هو معالجة مسألة القيمة الفارغة كقيمة افتراضية مقابل شيء String one = new String ("")؛ كمتغير عضو ، ثم إجراء فحص للقيمة الخالية قبل تعيين سلسلة تم تمريرها إلى المُنشئ.

من الرائع جدا كمية علوم الكمبيوتر الخام الستراتوسفيرية التي تم إجراؤها في جافا.

C ++ وما إلى ذلك لديه libs بائع ، نعم. يمكن لجاوا أن تفوقها على خوادم كبيرة الحجم بسبب مجموعة الأدوات الضخمة. كتل ثابتة المبدئ دراسة ، والبقاء معنا.


يمكنك استخدام Java Create Invocation Builder لتوليد المنشئ تلقائيًا باستخدام القيم الافتراضية.

ما عليك سوى إضافةGenerateMethodInvocationBuilder إلى الفصل الدراسي ، أو الواجهة ، وDefault إلى المعلمات في الأساليب التي تريد القيم الافتراضية فيها. سيتم إنشاء أداة إنشاء في وقت الترجمة ، باستخدام القيم الافتراضية التي حددتها مع التعليقات التوضيحية.

@GenerateMethodInvocationBuilder
public class CarService {
 public CarService() {
 }

 public String getCarsByFilter(//
   @Default("Color.BLUE") Color color, //
   @Default("new ProductionYear(2001)") ProductionYear productionYear,//
   @Default("Tomas") String owner//
 ) {
  return "Filtering... " + color + productionYear + owner;
 }
}

ثم يمكنك استدعاء الأساليب.

CarService instance = new CarService();
String carsByFilter = CarServiceGetCarsByFilterBuilder.getCarsByFilter()//
  .invoke(instance);

أو قم بتعيين أي من القيم الافتراضية إلى شيء آخر.

CarService instance = new CarService();
String carsByFilter = CarServiceGetCarsByFilterBuilder.getCarsByFilter()//
  .withColor(Color.YELLOW)//
  .invoke(instance);

لا ، ولكن أبسط طريقة لتنفيذ ذلك هي:

public MyParameterizedFunction(String param1, int param2, Boolean param3) {

    param3 = param3 == null ? false : param3;
}

public MyParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}

أو بدلاً من المشغل الثلاثي الذي يمكنك استخدامه إذا:

public MyParameterizedFunction(String param1, int param2, Boolean param3) {

    if (param3 == null) {
        param3 = false;
    }
}

public MyParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}




method-overloading