在Java中接受不同类型的参数

时间:2013-10-11 08:38:12

标签: java overloading

这是一个关于我不确定如何在Java中解决的问题。我想根据三种类型的数据(URI,String或Literal)制作三重语句,每种类型的编码方式不同。我编写了接受这些类型的编码方法。

public static String makeStatement(URI subject, URI predicate, String object) {
    return " " + encode(subject) + " " + encode(predicate) + " " + encode(object) + ".\n";
}

public static String makeStatement(String subject, URI predicate, String object) {
    return " " + encode(subject) + " " + encode(predicate) + " " + encode(object) + ".\n";
}

public static String makeStatement(URI subject, URI predicate, Literal object) {
    return " " + encode(subject) + " " + encode(predicate) + " " + encode(object) + ".\n";
}

private static String encode(String binding) {
    return "?" + binding;
}

private static String encode(URI uri) {
    return "<" + uri.stringValue() + ">";
}

private static String encode(Literal literal) {
    return "\"" + literal.stringValue() + "\"" + literal.getDatatype();
}

但是因为我可以接受这些类型的任何组合,这将需要9个makeStatement函数,这些函数基本上做同样的事情,这似乎是一个坏主意,特别是因为我可能希望稍后添加另一种类型。

通常我会回答这个问题,建议创建一个superClass,但我不能编辑String,URI和Literal。另一种选择是定义

public static String makeStatement(Object subject, Object predicate, Object object) {
    String encodedSubject = "", encodedPredicate = "", encodedObject = "";
    if (subject.getClass().equals(URI.class)) {
        encodedSubject = encode((URI) subject);
}
    return " " + encode(encodedSubject) + " " + encode(encodedPredicate) + " " + encode(encodedObject) + ".\n";
}

然后检查每个参数的类,但我认为这不是很优雅。 另一个建议是定义类似makeStatement(URI subjectURI,String subjectString,Literal subjectLiteral,URI predicateURI等等),然后检查哪些参数为null并从那里开始,但这意味着当我调用时输入很多空值功能。 第三个选项是https://stackoverflow.com/a/12436592/1014666,但在调用makeStatement函数时,这又需要一些额外的输入。

有什么建议吗?

5 个答案:

答案 0 :(得分:3)

您可以使用构建器模式:

    public class StatementMaker {
    private static String encode(String binding) {
        return "?" + binding;
    }

    private static String encode(URI uri) {
        return "<" + uri.stringValue() + ">";
    }

    private static String encode(Literal literal) {
        return "\"" + literal.stringValue() + "\"" + literal.getDatatype();
    }

    public static Statement from(String b) {
        return new Statement(encode(b));
    }

    public static Statement from(URI b) {
        return new Statement(encode(b));
    }

    public static Statement from(Literal b) {
        return new Statement(encode(b));
    }

    public static class Statement {

        private StringBuilder buf;
        private Statement(String s) {
            buf = new StringBuilder(" ");
            buf.append(s);
        }

        public Statement with(String s) {
            buf.append(" ").append(encode(b));
            return this;
        }

        public Statement with(URI s) {
            buf.append(" ").append(encode(b));
            return this;
        }

        public Statement with(Literal s) {
            buf.append(" ").append(encode(b));
            return this;
        }

        public String toString() {
            return buf.toString() + ".\n";
        }

    }
}

您现在可以构建语句:

StatementMaker.from(subject).with(predicate).with(object).toString()

在需要语句的代码中,您可以使用静态导入进一步缩短代码:

import static my.package.StatementMaker.from;

然后声明缩小为:

from(subject).with(predicate).with(object).toString()

您可以向内部类添加3个方法:

public static class Statement {

    private StringBuilder buf;
    private Statement(String s) {
        buf = new StringBuilder(" ");
        buf.append(s);
    }

    public Statement with(String s) {
        buf.append(" ").append(encode(b));
        return this;
    }

    public Statement with(URI s) {
        buf.append(" ").append(encode(b));
        return this;
    }

    public Statement with(Literal s) {
        buf.append(" ").append(encode(b));
        return this;
    }

    public String and(String s) {
        buf.append(" ").append(encode(b));
        return buf.toString() + ".\n";
    }

    public String and(URI s) {
        buf.append(" ").append(encode(b));
        return buf.toString() + ".\n";
    }

    public String and(Literal s) {
        buf.append(" ").append(encode(b));
        return buf.toString() + ".\n";
    }


    public String toString() {
        return buf.toString() + ".\n";
    }

}

然后您可以使用避免toString()这样的调用:

String statement = from(subject).with(predicate).and(object);

答案 1 :(得分:2)

如果只有几个选项,方法重载效果很好。你在这里有点有点痴迷。如果有一种简单的方法可以从一种方式转换为另一种方式,则无需拥有所有选项。

所以忘记尽可能选择并使用最常用的选项。

答案 2 :(得分:1)

  

通常我会回答这样一个问题,建议创建一个超类,但我不能   编辑字符串,URI和文字。另一种选择是定义

我会采用类似的方法,但不是提取超类,如你所述,你不能这样做,你可以创建一个包装器。

public class LiteralWrapper {
    private String string = null;
    private URI uri = null;
    private Literal literal = null;

    public LiteralWrapper(String sting) {
        this.string = string;
    }

    public LiteralWrapper(URI uri) {
        this.uri = uri;
    }

    public LiteralWrapper(Literal literal) {
        this.literal = literal;
    }

    // Note that this class is immutable, 
    // so you know you cannot have more than one non-null member. 
    // Probably not a bad idea to add some getters, though.


    /* The encode functions from your original question */

    private static String encode(String binding) {
        return "?" + binding;
    }

    private static String encode(URI uri) {
        return "<" + uri.stringValue() + ">";
    }

    private static String encode(Literal literal) {
        return "\"" + literal.stringValue() + "\"" + literal.getDatatype();
    }

    @Override
    public String toString() {
        if (literal != literal) {
            return encode(literal);
        }
        if (uri != null) {
            return encode(uri);
        }
        return encode(string);
    }
}

现在,您的makeStatement代码变得微不足道了:

public static String makeStatement(LiteralWrapper subject, LiteralWrapper predicate, LiteralWrapper object) {
    return " " + subject + " " + predicate + " " + object + ".\n";
}

编辑:
根据下面的评论,这使得调用makeStatement有点烦人。你没有能够makeStatement(myString, myUri, myLiteral),而是强行召唤makeStatement(new LiteralWrapper(myString), new LiteralWrapper(myUri), new LiteralWrapper(myLiteral))。 使用给定的解决方案无法完全避免这个问题,但可以通过以工厂方法的形式引入一些语法糖来减轻这个问题:

public static LiteralWrapper wrap(String string) {
    return new LiteralWrapper(string);
}

public static LiteralWrapper wrap(URI uri) {
    return new LiteralWrapper(uri);
}

public static LiteralWrapper wrap(Literal literal) {
    return new LiteralWrapper(literal);
}

现在,您可以在需要使用makeStatement的任何地方静态导入这些包装器:

import static org.some.package.LiteralWrapper.wrap;
/* other imports*/

public class MyClass {
    public void someFunction() {
        /* some business logic */

        makeStatemet(wrap(myString), wrap(myURI), wrap(myLiteral));
    }
}

答案 3 :(得分:1)

public static String makeStatement(Object subject, Object predicate, Object object) {
    return " " + encode(subject) + " " + encode(predicate) + " " + encode(object) + ".\n";
}

private static String encode(Object obj) {
   String  encodedOj ="";
   if (obj.getClass().equals(URI.class)) {
        encodedOj = encode((URI) obj);
   }else if(obj.getClass().equals(Literal.class)){
      encodedOj = encode((Literal) obj);
   }else if(obj.getClass().equals(String.class)){
      encodedOj = encode((String) obj);
   } 
   return encodedOj;
}

private static String encode(String binding) {
    return "?" + binding;
}

private static String encode(URI uri) {
    return "<" + uri.stringValue() + ">";
}

private static String encode(Literal literal) {
    return "\"" + literal.stringValue() + "\"" + literal.getDatatype();
}

答案 4 :(得分:0)

您可以使用静态工厂方法(请参阅 Effective Java,Item 1 )和匿名类(充当类似闭包的东西)创建有趣且易于使用的包装器。

以下是:

public class Item {

    private static interface Methods {
        public String encode();
    }

    private final Methods methods;

    private Item(Methods methods) {
        this.methods = methods;
    }

    public static Item of(final String binding) {
        return new Item(new Methods() {
            @Override
            public String encode() {
                return "?" + binding;
            }
        });
    }

    public static Item of(final URI uri) {
        return new Item(new Methods() {
            @Override
            public String encode() {
                return "<" + uri.stringValue() + ">";
            }
        });
    }

    public static Item of(final Literal literal) {
        return new Item(new Methods() {
            @Override
            public String encode() {
                return "\"" + literal.stringValue() + "\"" + literal.getDatatype();
            }
        });
    }

    public String encode() {
        return methods.encode();
    }
}

使用这种方法添加新支持的类型(这是您的要求之一)非常简单:只需创建接受此类型的新静态工厂方法:Item.of(NewType val)

所以你会有一个方法:

public static String makeStatement(Item subject, Item predicate, Item object) {
    return subject.encode() + " " + predicate.encode() + " " + object.encode();
}

并称之为:

makeStatement(Item.of(subject), Item.of(predicate), Item.of(object));

添加新方法也很容易(但它有点像修改而不是扩展) - 只需将它们添加到Methods接口并在闭包中实现所有支持的类型。无论如何,编译器会让你。