How to use apache storm tuple - java

I just began with Apache Storm. I read the tutorial and had a look into examples My problem is that all example work with very simple tuples (often one filed with a string). The tuples are created inline (using new Values(...)). In my case i have tuples with many fields (5..100). So my question is how to implement such tuple with name and type (all primitive) for each field?
Are there any examples? (i think directly implementing "Tuple" isn't a good idea)
thanks

An alternative to creating the tuple with all of the fields as a value is to just create a bean and pass that inside the tuple.
Given the following class:
public class DataBean implements Serializable {
private static final long serialVersionUID = 1L;
// add more properties as necessary
int id;
String word;
public DataBean(int id, String word) {
setId(id);
setWord(word);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
}
Create and emit the DataBean in one bolt:
collector.emit(new Values(bean));
Get the DataBean in the destination bolt:
#Override
public void execute(Tuple tuple, BasicOutputCollector collector) {
try {
DataBean bean = (DataBean)tuple.getValue(0);
// do your bolt processing with the bean
} catch (Exception e) {
LOG.error("WordCountBolt error", e);
collector.reportError(e);
}
}
Don't forget to make your bean serializable and register when you set up your topology:
Config stormConfig = new Config();
stormConfig.registerSerialization(DataBean.class);
// more stuff
StormSubmitter.submitTopology("MyTopologyName", stormConfig, builder.createTopology());
Disclaimer: Beans will work fine for shuffle grouping. If you need to do a fieldsGrouping, you should still use a primitive. For example, in the Word Count scenario, you need go group by word so you might emit:
collector.emit(new Values(word, bean));

I would implement a custom tuple/value type as follows: Instead of using member variables to store the data, each attribute is mapped to a fixed index into the object list of the inherited Values types. This approach avoids the "field grouping" problem a regular Bean.
it in not required to add additional attributes for fields grouping (what is quite unnatural)
data duplication is avoided (reducing the number of shipped bytes)
it preserves the advantage of the beans pattern
An example for word count example would be something like this:
public class WordCountTuple extends Values {
private final static long serialVersionUID = -4386109322233754497L;
// attribute indexes
/** The index of the word attribute. */
public final static int WRD_IDX = 0;
/** The index of the count attribute. */
public final static int CNT_IDX = 1;
// attribute names
/** The name of the word attribute. */
public final static String WRD_ATT = "word";
/** The name of the count attribute. */
public final static String CNT_ATT = "count";
// required for serialization
public WordCountTuple() {}
public WordCountTuple(String word, int count) {
super.add(WRD_IDX, word);
super.add(CNT_IDX, count);
}
public String getWord() {
return (String)super.get(WRD_IDX);
}
public void setWort(String word) {
super.set(WRD_IDX, word);
}
public int getCount() {
return (Integer)super.get(CNT_IDX);
}
public void setCount(int count) {
super.set(CNT_IDX, count);
}
public static Fields getSchema() {
return new Fields(WRD_ATT, CNT_ATT);
}
}
To avoid inconsistencies, final static variables for "word" and "count" attribute are used. Furthermore, a method getSchema() returns the implemented schema to be used to declare output streams in Spout/Bolt method .declareOutputFields(...)
For output tuples, this type can be used straight forward:
public MyOutBolt implements IRichBolt {
#Override
public void execute(Tuple tuple) {
// some more processing
String word = ...
int cnt = ...
collector.emit(new WordCountTuple(word, cnt));
}
#Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(WordCountTuple.getSchema());
}
// other methods omitted
}
For input tuples, I would suggest the following pattern:
public MyInBolt implements IRichBolt {
// use a single instance for avoid GC trashing
private final WordCountTuple input = new WordCountTuple();
#Override
public void execute(Tuple tuple) {
this.input.clear();
this.input.addAll(tuple.getValues());
String word = input.getWord();
int count = input.getCount();
// do further processing
}
// other methods omitted
}
MyOutBolt and MyInBolt can be connected as follows:
TopologyBuilder b = ...
b.setBolt("out", new MyOutBolt());
b.setBolt("in", new MyInBolt()).fieldsGrouping("out", WordCountTuple.WRD_ATT);
Using fields grouping is straight forward, because WordCountTuple allows to access each attribute individually.

Related

Best way to manage settings without a file in Java

what do you think would be the best way to manage settings knowing that I have no use for them to be stored in a file.
Is a simple POJO like below with getters and setters enough?
public class Settings {
private int setting1;
private boolean setting2;
private String setting3;
public Settings() {
// Some default values in constructor
setting1 = 12;
setting2 = false;
setting3 = "A setting";
}
public int getSetting1() {
return setting1;
}
public void setSetting1(int setting1) {
this.setting1 = setting1;
}
public boolean isSetting2() {
return setting2;
}
public void setSetting2(boolean setting2) {
this.setting2 = setting2;
}
public String getSetting3() {
return setting3;
}
public void setSetting3(String setting3) {
this.setting3 = setting3;
}
}
Should I use something more advanced? Like a class that would capture the type of the parameter in question like Setting<Integer> setting1 = new Setting(12); ?
I thank you in advance for your answers.
Keep it simple.
Here's an immutable class that does everything you need. No more, no less:
public final class Settings {
public final int setting1;
public final boolean setting2;
public String setting3;
public Settings(int setting1, boolean setting2, String setting3) {
this.setting1 = setting1;
this.setting2 = setting2;
this.setting3 = setting3;
}
}
If you expect to compare Settings objects, then implement hashCode and equals.
Everything else is just ceremony until you actually need it.
If you are using Java 14, then save some key-strokes by using records:
public record Settings(int setting1, boolean setting2, String setting3) {}
If you can get the job done with your Setting class, I don't see any reason why you need to make it complex.
Getters and setters are introduce mutability. Its better you can create this class more immutable fashion. You can achieve this many ways. Here is two ways,
Builder Pattern
Create a static factory method instead of constructor (Static factory method pattern)

Java array list returning 0 value

I have created a class like this, which contains a bunch of arraylist as you can see. I've been setting the array with the methods add.. and then retrieving it with get.., when i tried to System.out.println numberofcitizen for example it is returning 0. Note that i have instantiated the class in another class to set the values.
public int numberOfCitizen;
private final ArrayList<Integer> citizenid = new ArrayList<>();
private final ArrayList<String> citizenName = new ArrayList<>();
private final ArrayList<Integer> citizenWaste = new ArrayList<>();
private final ArrayList<Float> longitude = new ArrayList<>();
private final ArrayList<Float> latitude = new ArrayList<>();
private final ArrayList<String> address = new ArrayList<>();
public void working() {
System.out.println("executing fine");
}
public void setnoOfcit(int number) {
this.numberOfCitizen = number;
}
public int getnumber() {
return this.numberOfCitizen;
}
public void addCitizenId(int citizen) {
citizenid.add(citizen);
}
public int getCitizenid(int i) {
int citId = citizenid.get(i);
return citId;
}
public void addCitizenName(String citizenname) {
citizenName.add(citizenname);
}
public String getCitizenName(int i) {
return citizenName.get(i);
}
public void addCitizenWaste(int waste) {
citizenWaste.add(waste);
}
public int getCitizenWaste(int i) {
return citizenWaste.get(i);
}
public void addLatitude(float lat) {
latitude.add(lat);
}
public float getLat(int i) {
return latitude.get(i);
}
public void addlng(float lng) {
longitude.add(lng);
}
public float getlng(int i) {
return longitude.get(i);
}
com.graphhopper.jsprit.core.problem.VehicleRoutingProblem.Builder vrpBuilder = com.graphhopper.jsprit.core.problem.VehicleRoutingProblem.Builder.newInstance();
public void runVPRSolver() {
System.out.println(numberOfCitizen);
System.out.println(getCitizenName(0));
//create a loop to fill parameters
Probable source of problem :
numberOfCitizen is a member attribute that you seem to never change. If you want it to represent the number of elements in your lists, either use citizenName.size() or increment the value of numberOfCitizen in one of the add methods.
Design flaw :
Your design takes for granted that your other class always use that one properly. Anytime you or someone uses that class, he must make sure that he add every single element manually. This adds code that could be grouped inside your class, which would be cleaner and easier to maintain.
So instead of several add method like this :
addCitizenid();
addCitizenName();
addCitizenWaste();
addLongitude();
addLatitude();
addAddress();
Design an other Citizen class which will contain those elements, and use a single list of instances of that class. That way you can use only one method :
private List<Citizen> citizenList = new ArrayList<>();
public void addCitizen(Citizen c) {
/*Add element in your list*/
citizenList.add(c);
}
This programming methodology is called "Encapsulation" which you can read about here
You need to increment numberOfCitizen in your add methods. For example:
public void addCitizenId(int citizen){
citizenid.add(citizen);
numberOfCitizen++;
}
I would also suggest encapsulating your variables into Objects, so create a citizen class:
public class Citizen {
private Integer id;
private Integer name;
private Integer waste;
}
And change your variable to an ArrayList of objects:
ArrayList<Citizen> citizens;

How to enable enum inheritance

I'm writing a library, which has a predefined set of values for an enum.
Let say, my enum looks as below.
public enum EnumClass {
FIRST("first"),
SECOND("second"),
THIRD("third");
private String httpMethodType;
}
Now the client, who is using this library may need to add few more values. Let say, the client needs to add CUSTOM_FIRST and CUSTOM_SECOND. This is not overwriting any existing values, but makes the enum having 5 values.
After this, I should be able to use something like <? extends EnumClass> to have 5 constant possibilities.
What would be the best approach to achieve this?
You cannot have an enum extend another enum, and you cannot "add" values to an existing enum through inheritance.
However, enums can implement interfaces.
What I would do is have the original enum implement a marker interface (i.e. no method declarations), then your client could create their own enum implementing the same interface.
Then your enum values would be referred to by their common interface.
In order to strenghten the requirements, you could have your interface declare relevant methods, e.g. in your case, something in the lines of public String getHTTPMethodType();.
That would force implementing enums to provide an implementation for that method.
This setting coupled with adequate API documentation should help adding functionality in a relatively controlled way.
Self-contained example (don't mind the lazy names here)
package test;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<HTTPMethodConvertible> blah = new ArrayList<>();
blah.add(LibraryEnum.FIRST);
blah.add(ClientEnum.BLABLABLA);
for (HTTPMethodConvertible element: blah) {
System.out.println(element.getHTTPMethodType());
}
}
static interface HTTPMethodConvertible {
public String getHTTPMethodType();
}
static enum LibraryEnum implements HTTPMethodConvertible {
FIRST("first"),
SECOND("second"),
THIRD("third");
String httpMethodType;
LibraryEnum(String s) {
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
static enum ClientEnum implements HTTPMethodConvertible {
FOO("GET"),BAR("PUT"),BLAH("OPTIONS"),MEH("DELETE"),BLABLABLA("POST");
String httpMethodType;
ClientEnum(String s){
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
}
Output
first
POST
Enums are not extensible. To solve your problem simply
turn the enum in a class
create constants for the predefined types
if you want a replacement for Enum.valueOf: track all instances of the class in a static map
For example:
public class MyType {
private static final HashMap<String,MyType> map = new HashMap<>();
private String name;
private String httpMethodType;
// replacement for Enum.valueOf
public static MyType valueOf(String name) {
return map.get(name);
}
public MyType(String name, String httpMethodType) {
this.name = name;
this.httpMethodType = httpMethodType;
map.put(name, this);
}
// accessors
public String name() { return name; }
public String httpMethodType() { return httpMethodType; }
// predefined constants
public static final MyType FIRST = new MyType("FIRST", "first");
public static final MyType SECOND = new MyType("SECOND", "second");
...
}
Think about Enum like a final class with static final instances of itself. Of course you cannot extend final class, but you can use non-final class with static final instances in your library. You can see example of this kind of definition in JDK. Class java.util.logging.Level can be extended with class containing additional set of logging levels.
If you accept this way of implementation, your library code example can be like:
public class EnumClass {
public static final EnumClass FIRST = new EnumClass("first");
public static final EnumClass SECOND = new EnumClass("second");
public static final EnumClass THIRD = new EnumClass("third");
private String httpMethodType;
protected EnumClass(String name){
this.httpMethodType = name;
}
}
Client application can extend list of static members with inheritance:
public final class ClientEnum extends EnumClass{
public static final ClientEnum CUSTOM_FIRST = new ClientEnum("custom_first");
public static final ClientEnum CUSTOM_SECOND = new ClientEnum("custom_second");
private ClientEnum(String name){
super(name);
}
}
I think that this solution is close to what you have asked, because all static instances are visible from client class, and all of them will satisfy your generic wildcard.
We Fixed enum inheritance issue this way, hope it helps
Our App has few classes and each has few child views(nested views), in order to be able to navigate between childViews and save the currentChildview we saved them as enum inside each Class.
but we had to copy paste, some common functionality like next, previous and etc inside each enum.
To avoid that we needed a BaseEnum, we used interface as our base enum:
public interface IBaseEnum {
IBaseEnum[] getList();
int getIndex();
class Utils{
public IBaseEnum next(IBaseEnum enumItem, boolean isCycling){
int index = enumItem.getIndex();
IBaseEnum[] list = enumItem.getList();
if (index + 1 < list.length) {
return list[index + 1];
} else if(isCycling)
return list[0];
else
return null;
}
public IBaseEnum previous(IBaseEnum enumItem, boolean isCycling) {
int index = enumItem.getIndex();
IBaseEnum[] list = enumItem.getList();
IBaseEnum previous;
if (index - 1 >= 0) {
previous = list[index - 1];
}
else {
if (isCycling)
previous = list[list.length - 1];
else
previous = null;
}
return previous;
}
}
}
and this is how we used it
enum ColorEnum implements IBaseEnum {
RED,
YELLOW,
BLUE;
#Override
public IBaseEnum[] getList() {
return values();
}
#Override
public int getIndex() {
return ordinal();
}
public ColorEnum getNext(){
return (ColorEnum) new Utils().next(this,false);
}
public ColorEnum getPrevious(){
return (ColorEnum) new Utils().previous(this,false);
}
}
you could add getNext /getPrevious to the interface too
#wero's answer is very good but has some problems:
the new MyType("FIRST", "first"); will be called before map = new HashMap<>();. in other words, the map will be null when map.add() is called. unfortunately, the occurring error will be NoClassDefFound and it doesn't help to find the problem. check this:
public class Subject {
// predefined constants
public static final Subject FIRST;
public static final Subject SECOND;
private static final HashMap<String, Subject> map;
static {
map = new HashMap<>();
FIRST = new Subject("FIRST");
SECOND = new Subject("SECOND");
}
private final String name;
public Subject(String name) {
this.name = name;
map.put(name, this);
}
// replacement for Enum.valueOf
public static Subject valueOf(String name) {
return map.get(name);
}
// accessors
public String name() {
return name;
}

Design - Check a condition before executing every method

I have a POJO named Document.java with 100+ member variables. There is a transformation layer, where I get the required data, transform it and store it in the Document class.
In the tranformation layer, I would like to set a member variable only if satisfies a certain criteria (based on available context).
So it would look something like this:
if(shouldGetExecuted1(context.getXXX())){
document.setField1(tranformDataForField1(availableData1));
}
if(shouldGetExecuted2(context.getXXX())){
document.setField2(tranformDataForField2(availableData2));
}
I want to do this for all the 100+ fields. Is there a clean way to do this?
Additional information
I don't want to use Strategy here as it would create too many classes as the no of strategies grow.
Try to use AOP. AspectJ allows you to define pointcuts (for example, some filtered set of methods) and control their execution via advices (before method call, after, around):
#Aspect
class ClassName {
...
#PointCut("call(public void ClassName.*(..))") //includes all void methods of ClassName object
public void myPointCut(){}
#Around("myPointCut()")
public void myLogicMethod(ProceedingJoinPoint thisJoinPoint) {
if(shouldGetExecuted1(context.getXXX())){
thisJoinPoint.proceed()
}
}
}
Here thisJoinPoint.proceed() will execute the body of the intercepted method.
Read docs about how to define pointcuts. In this example the same logic will be applied to all void methods of this class. You can define more accurate pointcuts via special expressions to provide different logic for each.
No, there is no clean way to do it in Java. You can find methods using reflection but there is no way to find variables such as "availableDataN". So you necessarily need to make "availableDataN" a field in order to find it using reflection.
The final code would be something as ugly as the following:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class X {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
Method shouldGetExecuted = X.class.getMethod("shouldGetExecuted" + i, String.class);
boolean b = (boolean) shouldGetExecuted.invoke(null, context.getXXX());
if (b) {
Method tranformDataForField = X.class.getMethod("tranformDataForField");
Field data = X.class.getField("availableData" + i);
Object result = tranformDataForField.invoke(null, data.get(null));
Method set = X.class.getMethod("setField" + i, TransformDataType.class);
set.invoke(null, result);
}
}
}
}
You need to adapt to your specific case. For instance, here I am assuming all fields and methods are static. If they are not, then you need to replace null with an instance reference.
If you are consistent in the naming of your methods, reflection could help a lot.
The following code assumes the following:
A Document class with fields like xxx or xxYy (getters/setters would be usually present but are not required for the code to work)
A Transformer class that has
the capability to determine based on context information, if a field should be processed. These methods are named shouldTransformXxx(context).
the capability to transform the content of the field (with input and output of the same type as the corresponding field in Document). These methods are named T transformXxx(T).
A DataProvider class that has methods to provide the untransformed data. these methods are named findXxx()
The code below is pretty optimistic - it will fail, if a shouldTransformXxx for any field misses, or if it returns true, the same applies for the findXxx and transformXxx methods. So you would have to create classes with 100 methods each, which seems non-ideal for me. But on the other hand, having a class with 100 members seems to lead to awkward situations anyway...
So here's the code:
public class Document {
private String name;
private int size;
#Override
public String toString() {
return "Document [name=" + name + ", size=" + size + "]";
}
}
public class Transformer {
public enum ContextType {
NAME, SIZE
}
public boolean shouldTransformName(Set<ContextType> context) {
return context.contains(ContextType.NAME);
}
public boolean shouldTransformSize(Set<ContextType> context) {
return context.contains(ContextType.SIZE);
}
public String transformName(String name) {
return "::" + name;
}
public int transformSize(int size) {
return size + 1;
}
}
public class DataProvider {
private final String name;
private final int size;
public DataProvider(String name, int size) {
this.name = name;
this.size = size;
}
public String findName() {
return name;
}
public int findSize() {
return size;
}
}
public class Main {
private static final String TRANSFORM_METHOD_PREFIX = "transform";
private static final String CHECK_METHOD_PREFIX = "shouldTransform";
private static final String DATAPROVIDER_METHOD_PREFIX = "find";
private final DataProvider dataProvider;
private final Transformer transformer;
public Main(DataProvider dataProvider, Transformer transformer) {
this.dataProvider = dataProvider;
this.transformer = transformer;
}
public Document transformFields(Set<ContextType> context)
throws ReflectiveOperationException {
Document document = new Document();
for (Field field : Document.class.getDeclaredFields()) {
String capitalizedfieldName = capitalize(field.getName());
Class<?> fieldType = field.getType();
if (shouldTransform(context, capitalizedfieldName)) {
Object data = findData(capitalizedfieldName);
Object transformed = transformData(capitalizedfieldName,
fieldType, data);
// in presence of a security manager, a reflective call of the
// setter could be performed
field.setAccessible(true);
field.set(document, transformed);
}
}
return document;
}
private Object transformData(String capitalizedfieldName,
Class<?> fieldType, Object data)
throws ReflectiveOperationException {
String methodName = TRANSFORM_METHOD_PREFIX + capitalizedfieldName;
Method method = Transformer.class.getMethod(methodName, fieldType);
return method.invoke(transformer, data);
}
private Object findData(String capitalizedfieldName)
throws ReflectiveOperationException {
String methodName = DATAPROVIDER_METHOD_PREFIX + capitalizedfieldName;
Method method = DataProvider.class.getMethod(methodName);
return method.invoke(dataProvider);
}
private boolean shouldTransform(Set<ContextType> context,
String capitalizedfieldName) throws ReflectiveOperationException {
String methodName = CHECK_METHOD_PREFIX + capitalizedfieldName;
Method method = Transformer.class.getMethod(methodName, Set.class);
return (Boolean) method.invoke(transformer, context);
}
private String capitalize(String fieldName) {
char upperCaseFirstChar = Character.toUpperCase(fieldName.charAt(0));
if (fieldName.length() > 1) {
return upperCaseFirstChar + fieldName.substring(1);
} else {
return Character.toString(upperCaseFirstChar);
}
}
public static void main(String[] args) throws ReflectiveOperationException {
DataProvider dataProvider = new DataProvider("sample", 1);
Set<ContextType> context = EnumSet.of(ContextType.NAME,
ContextType.SIZE);
Main main = new Main(dataProvider, new Transformer());
Document document = main.transformFields(context);
System.out.println(document);
}
}

Get Object from Field

CLARIFICATION:
I do not know the objects name. That is where the problem comes in. I am creating an object like such:
`new Object(String attributes);
I am trying to run code in another class such as:
***.getStuff();
the trick to it is, there is no name for the Object. but i do know what String attributes is
The question: Is there any way to accomplish this without using the dreaded for loop?
This question is a bit tricky to word, but I will try my best. What I want to is get an object that matches a particular field without making a messy for loop. Something along the lines of:
Object A has the field String name.
String nameObj = "Tickle";
Object A has the name "Tickle"
if(nameObj.equals(Object A)){
//bla bla
}
Very confusing wording, yes. Sorry about that. I want to use Object A in my code without having to figure out which object it is, assuming all I have is its name. I am looking for a shortcut around using a for loop, I suppose.
Feel free to ask questions about what I am looking for. Sorry about the terribly worded question.
Poor coding, but this is what I am looking for...
nameObj.getName().getObjectA();
If you have a bunch of objects with names, and you want to grab an object by its name, I suggest you look up the class HashMap. HashMap lets you put in objects under keys, and when you give the hash map a key it returns the object associated with that key. So in your example, the keys would be string names.
Take at this implementation, that demonstrates what #Patashu said, create a map to the objects, in this case I just add an abstract class at the top of all.
import java.util.HashMap;
public class FindMeBaby {
public static void main(String[] args) {
Factory.add(new NiceGuy("first one"));
Factory.add(new FirstChild("ok im late"));
System.out.println(Factory.get("first one")
.getVeryImportantInformationThatOnlyThisClassKnows());
}
}
abstract class ParentOfAll {
protected String id;
public ParentOfAll(String id) {
this.id = id;
}
public String getId(){
return id;
}
public abstract String getVeryImportantInformationThatOnlyThisClassKnows();
}
class FirstChild extends ParentOfAll {
public FirstChild(String id) {
super(id);
}
public String getVeryImportantInformationThatOnlyThisClassKnows() {
return "this is a secret";
}
}
class NiceGuy extends ParentOfAll {
public NiceGuy(String id) {
super(id);
}
public String getVeryImportantInformationThatOnlyThisClassKnows() {
return "to say the true, i'm not that nice :)";
}
}
class Factory {
private static HashMap allTheObjects = new HashMap();
public static Object add(ParentOfAll object) {
allTheObjects.put(object.getId(), object);
return object;
}
public static ParentOfAll get(String key) {
return (ParentOfAll) allTheObjects.get(key);
}
}
This is another version, of the same implementation with a more transparent aproach, without the Factory class, the Parent itself will keep track of the instances and save in a list.
import java.util.HashMap;
public class FindMeBaby {
public static void main(String[] args) {
NiceGuy foo = new NiceGuy("first one");
FirstChild bar = new FirstChild("ok im late");
System.out.println(ParentOfAll.get("first one")
.getVeryImportantInformationThatOnlyThisClassKnows());
}
}
abstract class ParentOfAll {
protected String id;
public ParentOfAll(String id) {
this.id = id;
add(this);
}
public String getId() {
return id;
}
public abstract String getVeryImportantInformationThatOnlyThisClassKnows();
private static HashMap allTheObjects = new HashMap();
private static Object add(ParentOfAll object) {
allTheObjects.put(object.getId(), object);
return object;
}
public static ParentOfAll get(String key) {
return (ParentOfAll) allTheObjects.get(key);
}
}
class FirstChild extends ParentOfAll {
public FirstChild(String id) {
super(id);
}
public String getVeryImportantInformationThatOnlyThisClassKnows() {
return "this is a secret";
}
}
class NiceGuy extends ParentOfAll {
public NiceGuy(String id) {
super(id);
}
public String getVeryImportantInformationThatOnlyThisClassKnows() {
return "to say the true, i'm not that nice :)";
}
}

Categories

Resources