Q
Q
qor1x2015-09-04 13:39:42
Java
qor1x, 2015-09-04 13:39:42

Java. Abstractions, interfaces, inheritance. How to implement?

I wanted to study OOP better, namely design, abstraction levels, etc. I took Java as the language.
Now I am writing a project in order to learn Zen and abstractions over abstractions and a few questions have arisen.
As an example, I will talk about people (Human).
For example, there is the main IHuman interface, which describes methods, void say(String text), void jump().
There is also a Human class with the Human(String name, Boolean kaduk) construct. But the objects get into the program "from the outside" (in my case, the database), so you need a method that will parse the data from the table and return the List collection. In my case, this is a static public method that is in the Human class. Is it correct? Or should such a method be statically in the interface itself? Or ...?
Second moment. People differ by gender and, against the background of this feature, behave differently when calling methods. In the case of say, their behavior is the same, but jump() is completely different. Also, when the collection is filled with data (people), we do not know what kind of object is slipped to us, this is determined later, by calling the void checkKaduk () method. My vision for all this sexism is as follows:
Create an abstract class AHuman that implements IHuman, describe the entire class structure (Properties, constructor) in it, and implement the say method. But then I don’t quite understand how to make a sex determination, calling the necessary jump method.
It is necessary to make two implementations of the type public class HumanManImpl extends AHuman { }, and the same for Woman and redefine jump in both, but in this case our parser from the database will not work, because here you immediately need to know what type is needed, but you cannot initialize an abstract class.
If I understand correctly, then we need to make another class that will support generics, at the time of parsing from the database, we don’t know which implementation is needed and specify <?>, then for each object from the new class with generics we call a method that will recognize gender by the presence of Adam's apple, and be converted (?) into the desired type. But I can't figure out how to implement it. Even if my conjectures are not correct, then I would still like to know the answer, how to implement the above.
Small snippets of code:

// Основной интерфейс
public interface Human {
    void say(String text);
    void jump();
}

// Абстрактный класс
public abstract class AHuman implements Human {
    public String name;
    public Boolean kaduk;

    public AHuman(String name, Boolean kaduk) {
        this.name = name;
        this.kaduk = kaduk;
    }

    public void checkKaduk() {
        if (kaduk) {
        } else {
        }
    }

    @Override
    public void say(String text) {
        System.out.println(String.format("%s: %s", name, text));
    }
}

// Реализация для Man
public class HumanManImpl extends AHuman {
    public HumanManImpl(String name, Boolean kaduk) {
        super(name, kaduk);
    }

    @Override
    public void jump() {
        System.out.println("Man");
    }
}

// для Woman
public class HumanWomanImpl extends AHuman {
    public HumanWomanImpl(String name, Boolean kaduk) {
        super(name, kaduk);
    }

    @Override
    public void jump() {
        System.out.println("Woman");
    }
}

Answer the question

In order to leave comments, you need to log in

2 answer(s)
N
nagibator8000, 2015-09-04
@qor1x

I would use composition, not inheritance. I would create the Action interface and from it the JumpAction class. Then the Human interface with one doAction method that would accept an Action. And then, based on Human, he created the Man and Woman classes and implemented unique logic for each class.
UPD. sketched out the code

public static interface Action {
        void apply(int power);
        String getActionName();
    }

    public static class JumpAction implements Action {

        private int gravity;

        public JumpAction(int gravity) {
            this.gravity = gravity;
        }

        @Override
        public void apply(int power) {
            if (power > gravity) {
                System.out.println("прыгает на " + (power - gravity) + " метров...");
            } else {
                System.out.println("немогу подпрыгнуть...");
            }
        }

        @Override
        public String getActionName() {
            return "прыжок";
        }
    }

    public static interface Human {
        void doAction(Action action);
    }

    public static class Man implements Human {

        public String name;
        private int power = 10;

        public Man(String name) {
            this.name = name;
        }

        @Override
        public void doAction(Action action) {
            System.out.println(name + " делает " + action.getActionName());
            action.apply(power);
        }
    }

    public static class Woman implements Human {
        public String name;
        private int power = 7;

        public Woman(String name) {
            this.name = name;
        }

        @Override
        public void doAction(Action action) {
            System.out.println(name + " вертя задницей делает " + action.getActionName());
            action.apply(power);
        }
    }

    public static void main(String[] args) {
        JumpAction jump = new JumpAction(8);
        Man man = new Man("Анатолий");
        man.doAction(jump);
        Woman woman = new Woman("Наталья");
        woman.doAction(jump);
    }

Will issue
Анатолий делает прыжок
прыгает на 2 метров...
Наталья вертя задницей делает прыжок
немогу подпрыгнуть...

B
bromzh, 2015-09-04
@bromzh

Determine which class to use from the outside. There are all sorts of factory patterns for this . And the check inside the abstract class must be removed.
And it is desirable to avoid static methods, although they can be used in simple factories.
The list must be parameterized with the Human type, and the class must be parameterized as . Or just use the Human type everywhere, as if polymorphism was invented for this.
UPD

public interface Human {
    public void jump();
    public void say(String text);
}


public abstract class AbstractHuman implements Human {
    protected String name;

    public AbstractHuman(String name) {
        this.name = name;
    }

    @Override
    public void say(String text) {
        System.out.println(name + ": " + text);
    }
}


public class Man extends AbstractHuman {
    public Man(String name) {
        super(name);
    }

    @Override
    public void jump() {
        System.out.println("Man jump");
    }
}


public class Woman extends AbstractHuman {
    public Woman(String name) {
        super(name);
    }

    @Override
    public void jump() {
        System.out.println("Woman jump");
    }
}


public interface HumanFactory {
    public static Human createHuman(String name, boolean kadyk) {
        if (kadyk) {
            return new Man(name);
        }
        return new Woman(name);
    }
}

import java.util.LinkedList;
import java.util.List;

public class Main  {
    static class DBData {
        String name;
        boolean kadyk;
        public DBData(String name, boolean kadyk) {
            this.name = name;
            this.kadyk = kadyk;
        }
    }

    public static void main(String[] args) {
        List<DBData> source = new LinkedList<>();
        source.add(new DBData("Ваня", true));
        source.add(new DBData("Маша", false));
        source.add(new DBData("Катя", true));
        source.add(new DBData("Сергей", true));
        
        List<Human> humanList = new LinkedList<>();
        
        for(DBData data : source) {
            humanList.add(HumanFactory.createHuman(data.name, data.kadyk));
        }
        
        for(Human human : humanList) {
            human.say("Hello");
            human.jump();
        }
    }
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question