Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: Методы интерфейса java.util.List

Создать тестовый пример, демонстрирующий работу всех методов интерфейса java.util.List. В качестве коллекций, реализующих данный интерфейс выбрать класс ArrayList. Продемонстрировать один случай возникновения и обработки типового исключения при работе с данным интерфейсом.
Ответ:
Сообщение от КатеринаОбухова
Создать тестовый пример, демонстрирующий работу всех методов интерфейса java.util.List. В качестве коллекций, реализующих данный интерфейс выбрать класс ArrayList. Продемонстрировать один случай возникновения и обработки типового исключения при работе с данным интерфейсом.
Ок.
Вопрос: Работа с интерфейсами и шаблон Strategy - Проиллюстрировать использование интерфейсов

Задание к работе:
1. Проиллюстрировать использование интерфейсов.
2. Показать вызов метода интерфейса через интерфейсную ссылку.
3. Применить в программе шаблон проектирования Strategy.

Условие:
Предметная область: Интернет оператор. Информационная система провайдера хранит данные о клиентах. Некоторым клиентам предоставляется фиксированная скидка. В классе “оператор” реализовать метод добавления нового клиента и метод вычисления суммарной стоимости оказанных услуг.

Совсем запутался в этих интерфейсах. Понятия не имею как в моей проге это все реализовать эффективно и еще шаблон какой-то.

Моя программа.
Кликните здесь для просмотра всего текста
Customer
Код C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Customer
    {
        //Список купленных тарифов
        public List<Product> lstProdOfCust = new List<Product>();
        public string Name { get; set; }
 
        public Customer(string n)
        {
            Name = n;
        }
 
        //Купить тариф
        public void BuyProd(Product p)
        {
            lstProdOfCust.Add(p);
        }
 
        public int GetTotal()
        {
            int sum = 0;
            foreach (var p in lstProdOfCust)
                sum += p.Price;
            return sum;
        }
    }
Discount
Код C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Discount : IPrice
    {
        public int discount, price;
 
        public Discount(int p, int d)
        {
            price = p;
            discount = d;
        }
 
        public int GetPrice()
        {
            return price-discount;
        }
    }
IPrice
Код C#
1
2
3
4
interface IPrice
    {
        int GetPrice();
    }
NoDiscount
Код C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class NoDiscount : IPrice
    {
        public int price;
 
        public NoDiscount(int p)
        {
            price = p;
        }
 
        public int GetPrice()
        {
            return price;
        }
    }
Operator
Код C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
 class Operator
    {
        //Список тарифов
        public List<Product> lstPr = new List<Product>();
        //Список клиентов
        public List<Customer> lstCust = new List<Customer>();
 
        //Текущий клиент
        Customer currCust;
 
        //Добавить тариф
        public void AddProduct(string t, int p, int q)
        {
            lstPr.Add(new Product(t,p,q));
        }
 
        //Добавить клиента
        public void AddCustomer(string n)
        {
            lstCust.Add(new Customer(n));
        }
 
        //Поиск клиента заплатившего больше всех
        public Customer GetCustByPrice()
        {
            Customer cust = lstCust[0];
            foreach (var item in lstCust)
                if (item.GetTotal() > cust.GetTotal()) cust = item;
            return cust;
        }
 
        //Вывод общей стоимости реализованного трафика
        public int GetTotalSum()
        {
            int sum = 0;
            foreach (Customer c in lstCust)
            {
                foreach (Product p in c.lstProdOfCust)
                {
                    sum += p.Price;
                }
            }
            return sum;
        }
        //Поиск клиента по имени
        public Customer GetCustByName(string n)
        {
            foreach (Customer item in lstCust)
                if (item.Name == n)
                {
                    return item;
                }
            return null;
        }
       
        //Регистрация пользователя
        public void LogIn(String n)
        {
            if (currCust == null)
                currCust = GetCustByName(n);
        }
        
        //Выход из системы
        public void LogOut()
        {
            currCust = null;
        }
 
        //Найти тариф по названию
        public Product GetProdByTitle(string t)
        {
            foreach (Product item in lstPr)
            {
                if (item.Name == t)
                    return item;
            }
            return null;
        }
        //Купить тариф для текущего клиента
        public void BuyProduct(string name)
        {
            Product p = GetProdByTitle(name);
            currCust.BuyProd(p);
        }
        
        //Вывод данных о потребленном трафике для конкретного пользователя
        public string GetProductByName(string n)
        {
            Customer c = GetCustByName(n);
            string s = "Client: " + c.Name + "\n" + "Potreblenniy trafik: ";
            foreach (Product p in c.lstProdOfCust)
            {
                s += p.Trafik;
            }
            return s;
        }
    }
Product
Код C#
1
2
3
4
5
6
7
8
9
10
11
12
13
 class Product
    {
        public string Name { get; set; }
        public int Price { get; set; }
        public int Trafik { get; set; }
 
        public Product(string a, int p, int t)
        {
            Name = a;
            Price = p;
            Trafik = t;
        }
    }
Program
Код C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Program
    {
        static void Main()
        {
            Operator op = new Operator();
            op.AddProduct("Домовой", 100, 5000);
            op.AddProduct("10gb", 200, 10000);
            op.AddProduct("15gb", 300, 15000);
 
            op.AddCustomer("Petya");
            op.AddCustomer("Fedya");
            op.AddCustomer("Ivan");
 
            //Добавление клиентов со скидкой
            op.AddCustomer("Vasya");
            op.LogIn("Vasya");
 
            op.LogOut();
 
            op.LogIn("Petya");
            op.BuyProduct("15gb");
            op.LogOut();
 
            op.LogIn("Fedya");
            op.BuyProduct("10gb");
            op.LogOut();
 
            Console.WriteLine("Общая стоимость реализуемого трафика: " + op.GetTotalSum());
            Console.WriteLine(op.GetProductByName("Fedya"));
            Console.WriteLine(new string('-', 20));
            Console.WriteLine(op.GetCustByPrice().Name);
        }
    }


Пример препода.
Кликните здесь для просмотра всего текста
Код C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
using System;  
using System.Collections.Generic; 
 
 
interface IPrice 
{ 
    int GetPrice(); 
} 
 
class NoDiscount : IPrice 
{ 
    int price; 
    public NoDiscount(int p) 
    { 
        price = p; 
    } 
    public int GetPrice() 
    { 
        return price; 
    } 
} 
 
class AbsDiscount : IPrice 
{ 
    int price; 
    int discount; 
    public AbsDiscount(int p, int d) 
    { 
        price = p; 
        discount = d; 
    } 
    public int GetPrice() 
    { 
        return price - discount; 
    } 
} 
 
class Product 
{ 
    public Product(string name, IPrice ip) 
    { 
        Name = name; 
        this.ip = ip; 
    } 
    IPrice ip; 
    public string Name { get; set; } 
    public int GetPrice() 
    { 
        return ip.GetPrice(); 
    } 
} 
 
class Store 
{ 
    List<Product> lstProd = new List<Product>(); 
    public void AddNoDiscountProduct(string name, int price) 
    { 
        Product p = new Product(name, new NoDiscount(price)); 
        lstProd.Add(p); 
    } 
    public void AddAbsDiscountProduct(string name, int price, int discount) 
    { 
        Product p = new Product(name, new AbsDiscount(price, discount)); 
        lstProd.Add(p); 
    } 
    public int GetTotalPrice() 
    { 
        int s = 0; 
        foreach (Product p in lstProd) 
        { 
            s += p.GetPrice(); 
        } 
        return s; 
    } 
} 
 
class Program 
{ 
    static void Main(string[] args) 
    { 
        Store riga = new Store(); 
        riga.AddAbsDiscountProduct(" bread", 3200, 200); 
        riga.AddNoDiscountProduct("milk", 1200); 
        Console.WriteLine(riga.GetTotalPrice()); 
    } 
}


Добавлено через 8 часов 14 минут
Еще актуально)

Добавлено через 18 часов 38 минут
Никто не может помочь?)
Ответ: DebieCooper,
Цитата Сообщение от DebieCooper Посмотреть сообщение
Задание к работе:
1. Проиллюстрировать использование интерфейсов.
2. Показать вызов метода интерфейса через интерфейсную ссылку.
3. Применить в программе шаблон проектирования Strategy.
Условие:
Предметная область: Интернет оператор. Информационная система провайдера хранит данные о клиентах. Некоторым клиентам предоставляется фиксированная скидка. В классе “оператор” реализовать метод добавления нового клиента и метод вычисления суммарной стоимости оказанных услуг.
Код C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
using System;
using System.Collections.Generic;
 
namespace ConsoleApplication180
{
    class Program
    {
        static void Main(string[] args)
        {
            var users = new Users();
            var user1 = new User() { Name = "Петренко", TariffPrice = 100, CostCalcualtor = new NoDiscount() };
            var user2 = new User() { Name = "Сидоренко", TariffPrice = 150, CostCalcualtor = new AbsDiscount(10) };
 
            users.Add(user1);
            users.Add(user2);
 
            var sum = users.GetTotalCost();
 
            Console.WriteLine(sum);
 
            Console.ReadLine();
        }
    }
 
    class Users : List<User>
    {
        public int GetTotalCost()
        {
            int res = 0;
            foreach (var u in this)
                res += u.GetCost();
 
            return res;
        }
    } 
 
    class User
    {
        public string Name { get; set; }
        public int TariffPrice { get; set; }
 
        public ICostCalculator CostCalcualtor { get; set; }
 
        public int GetCost()
        {
            return CostCalcualtor.Calc(TariffPrice);
        }
    }
 
    interface ICostCalculator
    {
        int Calc(int price);
    }
 
    class NoDiscount : ICostCalculator
    {
        public int Calc(int price)
        {
            return price;
        }
    }
 
    class AbsDiscount : ICostCalculator
    {
        int discount;
 
        public AbsDiscount(int d)
        {
            discount = d;
        }
 
        public int Calc(int price)
        {
            return Math.Max(0, price - discount);
        }
    }
}
Вопрос: Как реализовать метод интерфейса внутри потока?

Итак, создаю класс:
Java
1
2
3
4
5
6
7
8
9
10
11
public class ArrayIsFull extends Exception{
    private int size;
    
    public ArrayIsFull(int UserSize) {
        size = UserSize;
    }
    
    public String GetMessage (){
        return "Your array is full! Max size is: " + size;
    }
}
После чего я создаю интерфейс
Java
1
2
3
public interface MyInterface <T> {
     void put (T UserValue) throws ArrayIsFull;
}
После чего создаю класс для основной работы программы:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class WorkerClass <T> implements Runnable, MyInterface<T> {
    T [] array; // Массив
    Thread flows; // Поток
    private int size;
    
    public WorkerClass(T  [] UserArray) {
        size = 0;
        array = UserArray;
        flows = new Thread (this);
        flows.start();
    }
 
    // И все, тут я застрял, что делать то?:)
    public void run() {
        // TODO Auto-generated method stub
 
    }
 
    // Этот метод мне нужно поместить в поток.
    public void put(T UserValue) throws ArrayIsFull {
        if (size == array.length){
            throw new ArrayIsFull (array.length);
        }
        array[size++] = UserValue;
    }
}
Ну и собственно сам главный класс:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
public class MainClass {
 
    public static void main(String[] args) {
        
        WorkerClass workerclass = new WorkerClass (/*object*/);
        
        try{
            workerclass.flows.join();
        } catch (InterruptedException message){
            System.out.println(message.getMessage());
        }
    }
}
Буду благодарен за помощь
Ответ: Спасибо)))
Мне в голову не пришло в параметры конструктора впихнуть другю реализацию анонимного класса реализируюшего уже другой интерфейс.
Вопрос: Расширенная версия интерфейса для потомка класса

Всех приветствую!

Возник вопрос при проектировании некой иерархии классов.
К примеру, есть следующая небольшая иерархия классов контролёров для представлений:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class IController 
{
public:
    virtual void add(/*...*/) = 0;
    virtual void edit(/*...*/) = 0;
    // ... и другие методы
    virtual ~IController() = default; 
};
 
class StandartController : public IController
{
public:
    void add(/*...*/) override;
    void edit(/*...*/) override;
};
Стандартные представления выполняют операции с моделью: добавить строку, удалить строку(-ки), редактировать.
В процессе выяснилось, что нужно предусмотреть расширенную версию контролёра для расширенной версии представления. Расширенное представление будет принимать ссылки на стандартные модели и контролёры с целью оперировать их данными (поиск, сортировка, делегирование команд простым контролёрам для выполнения базовых функций и так далее).

C++
1
2
3
4
5
6
7
8
9
class ExtentedController : public IController
{
public:
    void add(/*...*/) override;
    void edit(/*...*/) override;
    virtual void find(/*...*/);
    virtual void sort(/*...*/);
    // ... и другие методы
};
Как теперь при наличии расширенного потомка единообразно использовать интерфейс? Решение с dynamic_cast мне не нравится. Что если появится ещё пару расширенных версий? Для них использоваться тоже dynamic_cast? Второй вариант был выделить расширенный класс в совершенно новую иерархию. Но опять же - для каждой расширенной версии делать свою иерархию? Скорее всего имеются некоторые проблемы с архитектурой, раз возникла эта проблема.

Стоить также отметить, что для производства контролёров используется фабрика, которая возвращает только указатель на интерфейс (IController*) в независимости от того, какой тип объекта потребовался клиенту.
Сигнатура принимающего метода представления выглядит следующим образом:
C++
1
void setController(IContoller* ctrl);
Интерфейс представления:

C++
1
2
3
4
5
6
7
8
9
10
class IView
{
public:
   IView() = delete;
   IView(/*...*/);
   ~IView() = default;
   //...
   void setController(IContoller* ctrl);
   //... другие методы
};
При проектировании использовал принцип "программирования на уровне интерфейсов", но когда стали появляться реализации "не такие как все", возникли проблемы с их использованием. Ведь все представление знают только об интерфейсе контролёра. Можно, конечно, в представлении сделать каст к нужному типу, но повторюсь, меня так смущает эта операция, что я всё же ищу другое решение.
Ответ: Usagi,
Сообщение от Usagi
Методы фабрик обычных и расширенных контроллеров получают различное число параметров.
Это не проблема, так как есть variadic template( Шаблоны с переменным числом параметров).

К примеру, если вы в фабрике создаете и автоматически добавляете в эту фабрику контроллер типа T, и у типа T есть конструктор с неизвестным числом и типами параметров, то это будет выглядеть примерно так:
C++
1
2
3
4
5
6
7
8
9
10
11
...
template<typename T, typename... Arg, typename std :: enable_if<std :: base_of<ExtentedController, T> :: value, T> :: type* = nullptr>
T* addController( Args... arg )
{
    ...
    T* controller = new T( std :: forward<Args>( arg )... );
    ...
    _extentedController.push_back( controller );
 
}
...
Вопрос: Вызов функций, возвращающих указатель на структуру, из нативной dll

Тут на форуме уже не раз задавали вопросы, как вызвать функцию из нативной dll. И в случае, если функция возвращает "нормальный" тип, у меня с этим вопросов нет: DllImport и всё такое. Но вот если функция возвращает указатель на интерфейс, вот тут у меня возникли проблемы.
Имеется dll-ка (написана, кажется, на CBuilder), экспортирующая всего 2 функции. Так же имеются примеры работы с этой dll-кой в Delphi и в С++.

На Delphi это выглядит так:

Rtusbapi.pas

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
unit Rtusbapi;
 
interface
 
uses
    windows;
 
type
pSHORT = ^SHORT;
pBYTE = ^BYTE;
 
type
 
// структура, задающая режимы ввода данных для модуля USB-3000
INPUT_PARS_USB3000 = packed record   // (size=438)
    size : WORD;
    InputEnabled : BOOL;                                    // флажок разрешение/запрещение ввода данных (только при чтении)
    CorrectionEnabled : BOOL;                           // управление корректировкой входных данных (с АЦП)
    InputClockSource : WORD;                            // источник тактовых импульсов для ввода данных
    InputType : WORD;                                       // тип вводимых с модуля даных (АЦП или ТТЛ)
    SynchroType : WORD;                                 // тип синхронизации вводимых с модуля даных
    SynchroAdType : WORD;                               // тип аналоговой синхронизации
    SynchroAdMode : WORD;                               // режим аналоговой сихронизации
    SynchroAdChannel : WORD;                            // канал АЦП при аналоговой синхронизации
    SynchroAdPorog : SHORT;                             // порог срабатывания АЦП при аналоговой синхронизации
    ChannelsQuantity : WORD;                            // число активных логических каналов
    ControlTable : array [0..127] of WORD;          // управляющая таблица с активными логическими каналами
    InputFifoBaseAddress : WORD;                        // базовый адрес FIFO буфера ввода
    InputFifoLength : WORD;                             // длина FIFO буфера ввода
    InputRate : double;                                 // тактовая частота ввода данных в кГц
    InterKadrDelay : double;                            // межкадровая задержка в мс
    ChannelRate : double;                               // частота ввода фиксированного логического канала
    AdcOffsetCoef : array [0..7] of double;         // корректировочные коэф. смещение нуля для АЦП
    AdcScaleCoef : array [0..7] of double;          // корректировочные коэф. масштаба для АЦП
end;
pINPUT_PARS_USB3000 = ^INPUT_PARS_USB3000;
 
// структура, задающая режимы вывода данных для модуля USB-3000
OUTPUT_PARS_USB3000 = packed record    // (size = 18)
    size : WORD;
    OutputEnabled : BOOL;                               // разрешение/запрещение вывода данных
    OutputRate : double;                                    // частота вывода данных в кГц
    OutputFifoBaseAddress : WORD;                   // базовый адрес FIFO буфера вывода
    OutputFifoLength : WORD;                            // длина FIFO буфера вывода
end;
pOUTPUT_PARS_USB3000 = ^OUTPUT_PARS_USB3000;
 
// структура пользовательского ППЗУ
FLASH_USB3000 = packed record           // (size = 256)
    CRC16 : WORD;                                           // контрольная сумма
    size : WORD;                                            // размер структуры
    SerialNumber : array [0..8] of BYTE;            // серийный номер модуля
    Name : array [0..10] of BYTE;                       // название модуля
    Revision : CHAR;                                        // ревизия модуля
    DspType : array [0..16] of BYTE;                    // тип установленного DSP
    IsDacPresented : BYTE;                              // флажок наличия ЦАП
    DspClockout : DWORD;                                // тактовая частота DSP в Гц
    AdcOffsetCoef : array [0..7] of single;         // корректировочные коэф. смещения нуля для АЦП
    AdcScaleCoef : array [0..7] of single;          // корректировочные коэф. масштаба для АЦП
    DacOffsetCoef : array [0..1] of single;         // корректировочные коэф. смещения нуля для ЦАП
    DacScaleCoef : array [0..1] of single;          // корректировочные коэф. масштаба для ЦАП
    ReservedByte : array [0..128] of BYTE;          // зарезервировано
end;
pFLASH_USB3000 = ^FLASH_USB3000;
 
// структура, содержащая информацию о версии драйвера DSP
DSP_INFO_USB3000 = packed record    // (size = 18)
    Target : array [0..9] of BYTE;                  //  модуль, для которого предназначен данный драйвер DSP
    DrvLabel : array [0..5] of BYTE;                    // метка разработчика драйвера DSP
    DspMajor : BYTE;                                        // старшие число версии драйвера DSP
    DspMinor : BYTE;                                        // младшее число версии драйвера DSP
end;
pDSP_INFO_USB3000 = ^DSP_INFO_USB3000;
 
// интерфейс модуля USB3000                                       `
IRTUSB3000 = class
  public
    // USB интерфейс модуля
    Function OpenDevice(VirtualSlot : WORD) : boolean; virtual; stdcall; abstract;
    Function CloseDevice : boolean; virtual; stdcall; abstract;
    Function GetModuleHandle : THandle; virtual; stdcall; abstract;
    Function GetUsbSpeed(UsbSpeed : pByte) : boolean; virtual; stdcall; abstract;
    Function GetModuleName(ModuleName : pCHAR) : boolean; virtual; stdcall; abstract;
    Function GetModuleSerialNumber(SerialNumber : pCHAR) : boolean; virtual; stdcall; abstract;
    Function GetAvrVersion(AvrVersion : pCHAR) : boolean; virtual; stdcall; abstract;
    Function ReleaseInstance : boolean; virtual; stdcall; abstract;
 
    // функции для работы с DSP модуля
    Function RESET_DSP : boolean; virtual; stdcall; abstract;
    Function LOAD_DSP(FileName : pCHAR = nil) : boolean; virtual; stdcall; abstract;
    Function MODULE_TEST : boolean; virtual; stdcall; abstract;
    Function GET_DSP_INFO(DspInfo : pDSP_INFO_USB3000): boolean; virtual; stdcall; abstract;
    Function SEND_COMMAND(Command : WORD) : boolean; virtual; stdcall; abstract;
 
    // функции для работы с памятью DSP модуля
    Function PUT_VAR_WORD(Address : WORD; Data : SHORT) : boolean; virtual; stdcall; abstract;
    Function GET_VAR_WORD(Address : WORD; Data : pSHORT) : boolean; virtual; stdcall; abstract;
    Function PUT_DM_WORD(Address : WORD; Data : SHORT) : boolean; virtual; stdcall; abstract;
    Function GET_DM_WORD(Address : WORD; Data : pSHORT) : boolean; virtual; stdcall; abstract;
    Function PUT_PM_WORD(Address : WORD; Data : DWORD) : boolean; virtual; stdcall; abstract;
    Function GET_PM_WORD(Address : WORD; Data : pDWORD) : boolean; virtual; stdcall; abstract;
    Function PUT_DM_ARRAY(BaseAddress, NPoints : WORD; Data : pSHORT) : boolean; virtual; stdcall; abstract;
    Function GET_DM_ARRAY(BaseAddress, NPoints : WORD; Data : pSHORT) : boolean; virtual; stdcall; abstract;
    Function PUT_PM_ARRAY(BaseAddress, NPoints : WORD; Data : pDWORD) : boolean; virtual; stdcall; abstract;
    Function GET_PM_ARRAY(BaseAddress, NPoints : WORD; Data : pDWORD) : boolean; virtual; stdcall; abstract;
 
    // функции для работы в режиме ввода данных
    Function GET_INPUT_PARS(ap : pINPUT_PARS_USB3000) : boolean; virtual; stdcall; abstract;
    Function SET_INPUT_PARS(ap : pINPUT_PARS_USB3000) : boolean; virtual; stdcall; abstract;
    Function START_READ : boolean; virtual; stdcall; abstract;
    Function STOP_READ : boolean; virtual; stdcall; abstract;
    Function READ_KADR(Data : pSHORT) : boolean; virtual; stdcall; abstract;
    Function READ_SAMPLE(Channel : WORD; Sample : pSHORT) : boolean; virtual; stdcall; abstract;
    Function ReadData(lpBuffer : pSHORT; nNumberOfWordsToRead, lpNumberOfBytesRead : pDWORD; lpOverlapped : POverlapped) : boolean; virtual; stdcall; abstract;
 
    // функции для работы в режиме вывода данных
    Function GET_OUTPUT_PARS(dp : pOUTPUT_PARS_USB3000) : boolean; virtual; stdcall; abstract;
    Function SET_OUTPUT_PARS(dp : pOUTPUT_PARS_USB3000) : boolean; virtual; stdcall; abstract;
    Function START_WRITE : boolean; virtual; stdcall; abstract;
    Function STOP_WRITE : boolean; virtual; stdcall; abstract;
    Function WRITE_SAMPLE(Channel : WORD; Sample : pSHORT) : boolean; virtual; stdcall; abstract;
    Function WriteData(lpBuffer : pSHORT; nNumberOfWordsToWrite, lpNumberOfBytesWritten : pDWORD; lpOverlapped : POverlapped) : boolean; virtual; stdcall; abstract;
 
    // функции для работы с ТТЛ линиями
    Function ENABLE_TTL_OUT(EnabledTtlOut : boolean) : boolean; virtual; stdcall; abstract;
    Function TTL_OUT(TtlOut : WORD) : boolean; virtual; stdcall; abstract;
    Function TTL_IN(TtlIn : pWORD) : boolean; virtual; stdcall; abstract;
 
    // функции для работы ППЗУ
    Function ENABLE_FLASH_WRITE(EnableFlashWrite : boolean) : boolean; virtual; stdcall; abstract;
    Function PUT_FLASH(fi : pFLASH_USB3000) : boolean; virtual; stdcall; abstract;
    Function GET_FLASH(fi : pFLASH_USB3000) : boolean; virtual; stdcall; abstract;
 
    // функция выдачи строки с последней ошибкой
    Function GetLastErrorString(lpBuffer : pCHAR; nSize : DWORD) : Integer; virtual; stdcall; abstract;
end;
PIRTUSB3000 = ^IRTUSB3000;
 
const
// текущая версия библиотеки Rtusbapi.dll
    VERMAJOR_RTUSBAPI           =   $0001;
    VERMINOR_RTUSBAPI           =   $0005;
    CURRENT_VERSION_RTUSBAPI    =   ((VERMAJOR_RTUSBAPI shl 16) or VERMINOR_RTUSBAPI);
 
// объявление экспортируемых из Rtusbapi.dll функций
Function RtGetDllVersion : DWORD; stdcall;
Function RtCreateInstance(DeviceName : PChar) : Pointer; stdcall;
 
implementation
    Function RtGetDllVersion : DWORD; External 'Rtusbapi.dll'
    Function RtCreateInstance(DeviceName : PChar) : Pointer; External 'Rtusbapi.dll'
end.
Вызываются эти функции так:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var
    // версия библиотеки Rtusbapi.dll
    DllVersion : DWORD;
 
    // интерфейс модуля USB3000
    pModule : IRTUSB3000;
begin
    // проверим версию используемой DLL библиотеки
    DllVersion := RtGetDllVersion; // <-- тут всё понятно
    if DllVersion <> CURRENT_VERSION_RTUSBAPI then
        begin
            ErrorString := 'Неверная версия DLL библиотеки Rtusbapi.dll! ' + #10#13 +
                        '           Текущая: ' + IntToStr(DllVersion shr 16) +  '.' + IntToStr(DllVersion and $FFFF) + '.' +
                        ' Требуется: ' + IntToStr(CURRENT_VERSION_RTUSBAPI shr 16) + '.' + IntToStr(CURRENT_VERSION_RTUSBAPI and $FFFF) + '.';
            TerminateApplication(ErrorString);
        end
    else WriteLn(' DLL Version --> OK');
 
    // попробуем получить указатель на интерфейс для модуля USB3000
    pModule := RtCreateInstance(pCHAR('usb3000')); // <-- а тут на Delphi тоже всё выглядит просто
    if pModule = nil then TerminateApplication('Не могу найти интерфейс модуля USB3000!')
    else WriteLn(' Module Interface --> OK');
 
    // попробуем обнаружить модуль USB3000 в первых 127 виртуальных слотах
    for i := 0 to 126 do
    if pModule.OpenDevice(i) then break; 
 
// и т.д.
Ответ: Ок, переделал. Сделал в точности как советовал товарищ Sam Harwell из ссылки в 5м посте, через interface. Чтобы вызывалось вот так:
C#
1
2
            IRTUSB3000 pModule = USB3000.GetRTUSB3000Interface();
            bool b = pModule.OpenDevice(0);
Rtusbapi.cs
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
using System;
using System.Runtime.InteropServices;
using System.Threading;
 
 
namespace Rtusbapi
{
    abstract class USB3000_Consts
    {
        public const ushort VarsBaseAddress_USB3000           =   0x30;
     // ...
    }
 
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct INPUT_PARS_USB3000        // size = 438 
    {
        public ushort size;
        [MarshalAs(UnmanagedType.Bool)]
        public bool InputEnabled;
// и т.д.
    }
 
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct OUTPUT_PARS_USB3000                       // size = 18 
    {
// и т.д.
    }
 
// и т.д.
 
    internal interface IRTUSB3000
    {
        bool OpenDevice(ushort VirtualSlot);
        bool CloseDevice();
        long GetModuleHandle();
        bool GetUsbSpeed(byte UsbSpeed);
        bool GetModuleName(string ModuleName);
        bool GetModuleSerialNumber(string SerialNumber);
        bool GetAvrVersion(string AvrVersion);
        bool ReleaseInstance();
 
        bool RESET_DSP();
        bool LOAD_DSP(string FileName);
        bool MODULE_TEST();
        bool GET_DSP_INFO(DSP_INFO_USB3000 DspInfo);
        bool SEND_COMMAND(ushort Command);
 
        bool PUT_VAR_WORD(ushort Address, short Data);
        bool GET_VAR_WORD(ushort Address, short Data);
        bool PUT_DM_WORD(ushort Address, short Data);
        bool GET_DM_WORD(ushort Address, short Data);
        bool PUT_PM_WORD(ushort Address, int Data);
        bool GET_PM_WORD(ushort Address, int Data);
        bool PUT_DM_ARRAY(ushort BaseAddress, ushort NPoints, short Data);
        bool GET_DM_ARRAY(ushort BaseAddress, ushort NPoints, short Data);
        bool PUT_PM_ARRAY(ushort BaseAddress, ushort NPoints, int Data);
        bool GET_PM_ARRAY(ushort BaseAddress, ushort NPoints, int Data);
 
        bool GET_INPUT_PARS(INPUT_PARS_USB3000 ap);
        bool SET_INPUT_PARS(INPUT_PARS_USB3000 ap);
        bool START_READ();
        bool STOP_READ();
        bool READ_KADR(short Data);
        bool READ_SAMPLE(ushort Channel, short Sample);
        bool ReadData(short lpBuffer, uint nNumberOfWordsToRead, uint lpNumberOfBytesRead, Overlapped lpOverlapped);
 
        bool GET_OUTPUT_PARS(OUTPUT_PARS_USB3000 dp);
        bool SET_OUTPUT_PARS(OUTPUT_PARS_USB3000 dp);
        bool START_WRITE();
        bool STOP_WRITE();
        bool WRITE_SAMPLE(ushort Channel, short Sample);
        bool WriteData(short lpBuffer, uint nNumberOfWordsToWrite, uint lpNumberOfBytesWritten, Overlapped lpOverlapped);
 
        bool ENABLE_TTL_OUT(bool EnabledTtlOut);
        bool TTL_OUT(ushort TtlOut);
        bool TTL_IN(ushort TtlIn);
 
        bool ENABLE_FLASH_WRITE(bool EnableFlashWrite);
        bool PUT_FLASH(FLASH_USB3000 fi);
        bool GET_FLASH(FLASH_USB3000 fi);
 
        int GetLastErrorString(string lpBuffer, int nSize);
    }
 
    internal static class USB3000
    {
        const uint VERMAJOR_RTUSBAPI = 0x1;
        const uint VERMINOR_RTUSBAPI = 0x5;
        public const uint CURRENT_VERSION_RTUSBAPI = ((VERMAJOR_RTUSBAPI << 0x10) | VERMINOR_RTUSBAPI);
 
        [DllImport(@"Rtusbapi.dll")]
        public static extern uint RtGetDllVersion();
 
        public static IRTUSB3000 GetRTUSB3000Interface()
        {
            IntPtr self = RtCreateInstance("usb3000");
            NativeRTUSB3000 nativeRTUSB3000 = (NativeRTUSB3000)Marshal.PtrToStructure(self, typeof(NativeRTUSB3000)); // <-- вылетает тут
            return new NativeRTUSB3000Wrapper(
                self,
                nativeRTUSB3000.OpenDevice,
                nativeRTUSB3000.CloseDevice,
                nativeRTUSB3000.GetModuleHandle,
                nativeRTUSB3000.GetUsbSpeed,
                nativeRTUSB3000.GetModuleName,
                nativeRTUSB3000.GetModuleSerialNumber,
                nativeRTUSB3000.GetAvrVersion,
                nativeRTUSB3000.ReleaseInstance,
// и т.д.
                );
        }
 
        [DllImport(@"Rtusbapi.dll", EntryPoint = "RtCreateInstance", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] // если Cdecl, то вылетает ошибка PInvokeStackImbalance was detected
        public static extern IntPtr RtCreateInstance([MarshalAs(UnmanagedType.LPStr)]string DeviceName);
 
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate bool OpenDeviceDelegate(IntPtr self, ushort VirtualSlot);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate bool CloseDeviceDelegate(IntPtr self);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate long GetModuleHandleDelegate(IntPtr self);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate bool GetUsbSpeedDelegate(IntPtr self, byte UsbSpeed);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate bool GetModuleNameDelegate(IntPtr self, string ModuleName);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate bool GetModuleSerialNumberDelegate(IntPtr self, string SerialNumber);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate bool GetAvrVersionDelegate(IntPtr self, string AvrVersion);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate bool ReleaseInstanceDelegate(IntPtr self);
// и т.д.
 
        private struct NativeRTUSB3000
        {
            public OpenDeviceDelegate OpenDevice;
            public CloseDeviceDelegate CloseDevice;
            public GetModuleHandleDelegate GetModuleHandle;
            public GetUsbSpeedDelegate GetUsbSpeed;
            public GetModuleNameDelegate GetModuleName;
            public GetModuleSerialNumberDelegate GetModuleSerialNumber;
            public GetAvrVersionDelegate GetAvrVersion;
            public ReleaseInstanceDelegate ReleaseInstance;
// и т.д.
        }
 
        private sealed class NativeRTUSB3000Wrapper : IRTUSB3000
        {
            private IntPtr _self;
            private OpenDeviceDelegate _OpenDevice;
            private CloseDeviceDelegate _CloseDevice;
            private GetModuleHandleDelegate _GetModuleHandle;
            private GetUsbSpeedDelegate _GetUsbSpeed;
            private GetModuleNameDelegate _GetModuleName;
            private GetModuleSerialNumberDelegate _GetModuleSerialNumber;
            private GetAvrVersionDelegate _GetAvrVersion;
            private ReleaseInstanceDelegate _ReleaseInstance;
// и т.д.
 
            public NativeRTUSB3000Wrapper(
                IntPtr self,
                OpenDeviceDelegate OpenDevice,
                CloseDeviceDelegate CloseDevice,
                GetModuleHandleDelegate GetModuleHandle,
                GetUsbSpeedDelegate GetUsbSpeed,
                GetModuleNameDelegate GetModuleName,
                GetModuleSerialNumberDelegate GetModuleSerialNumber,
                GetAvrVersionDelegate GetAvrVersion,
                ReleaseInstanceDelegate ReleaseInstance,
// и т.д.
                GetLastErrorStringDelegate GetLastErrorString)
            {
                this._self = self;
                this._OpenDevice = OpenDevice;
                this._CloseDevice = CloseDevice;
                this._GetModuleHandle = GetModuleHandle;
                this._GetUsbSpeed = GetUsbSpeed;
                this._GetModuleName = GetModuleName;
                this._GetModuleSerialNumber = GetModuleSerialNumber;
                this._GetAvrVersion = GetAvrVersion;
                this._ReleaseInstance = ReleaseInstance;
// и т.д.
            }
 
            public bool OpenDevice(ushort VirtualSlot)
            {
                return _OpenDevice(_self, VirtualSlot);
            }
 
            public bool CloseDevice()
            {
                return _CloseDevice(_self);
            }
// и т.д.
        }
    } 
}
Вылетает в стоке 97
InvalidFunctionPointerInDelegate was detected
Недействительный указатель на функцию 0xffffffff был передан в среду выполнения для преобразования в делегат. Передача недействительных указателей на функции для преобразования в делегаты может вызвать ошибки, а также повреждение или потерю данных.
Прикладываю на всякий случай проект.
Вопрос: Разные реализации одного интерфейса

Есть в javax.swing два класса, которые одновременно очень похожи, но в то же время и сильно различаются - это JList и JTable. Понадобилось мне создать класс, который имеет внутри себя реализацию либо одну, либо другую, но скрывает это от остальных и притворяется обычным java.awt.Component с реализацией некоего доп. интерфейса. Почему нужен именно java.awt.Component? Чтобы инстансы данного класса без проблем передавать во всякие java.awt.Container.add() и спокойно его отрисовывать.
Казалось бы, заурядная задача, но тут возникает неразрешимая для меня проблема. Допустим есть интерфейс addRemoveInterface со всеми методами:
Java
1
2
3
4
public interface AddRemoveInterface {
   public void add(Object o);
   public void remove (Object o);
}
Тогда делаем 2 класса, этот интерфейс наследующие:
Java
1
2
3
4
5
6
7
8
public class MyList extends JList implements AddRemoveInterface {
   public void add(Object o) {реализация};
   public void remove (Object o) {реализация};
}
public class MyTable extends JTable implements AddRemoveInterface {
   public void add(Object o) {реализация};
   public void remove (Object o) {реализация};
}
Но беда! Как экземпляр такого класса передавать куда-то еще? Если как (Сomponent) aInstance, то низя пользоваться методами интерфейса, а если как (addRemoveInterface), то передавать в java.awt.Container.add() на отрисовку.

В голову приходит другая мысль - а зачем нам отдельный интерфейс, если нам нужен подкласс java.awt.Component, и идем делать следующее:
Java
1
2
3
4
public abstract class AbstractAddRemoveComponent extends java.awt.Component {
   public abstract void add(Object o);
   public abstract void remove (Object o);
}
Казалось бы, все хорошо, но как теперь указать, что у класса MyList реализация будет на основе JList, а у MyTable - JTable соответственно. Т.е. чтобы при запуске такого экземпляра куда-нибудь в java.awt.Container.add() отрисовывался либо JList, либо JTable. Если бы данный метод принимал на себя экземпляр не класса, а интерфейса, то все было бы ок, их бы можно было бы наследовать несколько и не иметь проблем. Через дженерики я тоже решения проблемы не вижу
ps: пишу в J2SE, тк вопрос в первую очередь по языку, и то, что речь идет java.awt и javax.swing абсолютно вторично.

Добавлено через 1 час 39 минут
Ааа жесть какая, оказывается в java дженерики допускают множественное наследование класса и интерфейсов. Причем сделано это максимально непонятно, нельзя просто написать <T extends Class implements Interface1, Interface 1>, а надо писать через мать его амперсанд, а даже не через запятую.
Поэтому в моем случае надо создать просто 2 класса, реализующие интерфейс, как в примере выше:
Java
1
2
3
4
5
6
7
8
public class MyList extends JList implements AddRemoveInterface {
   public void add(Object o) {реализация};
   public void remove (Object o) {реализация};
}
public class MyTable extends JTable implements AddRemoveInterface {
   public void add(Object o) {реализация};
   public void remove (Object o) {реализация};
}
Но а передавать такие объекты уже в дженерик методы вроде
Java
1
public void <T extends Component & AddRemoveInterface> doSmth(T yoba_object) {тут вся движуха с объектом}
Ответ:
Сообщение от xave
перечислять наследуемые интерфейсы в классе/интерфейсе через запятую
Так было изначально.

Сообщение от xave
а в типе дженерика через амперсанды
Там запятая уже занята.

Java
1
2
3
Function<T, R>
// например
Function<T super U, R extends V>
Вопрос: Являются ли хорошей практикой одинаковые имена методов нескольких интерфейсов в одной реализации?

Здравствуйте, да, в C# можно в одном классе реализовать несколько методов интерфейсов с одинаковыми именами, но стоит ли так делать? Для меня, очевидное неудобство, заключается в том, что необходимо будет приводить объект к нужному типу для доступа к необходимым к методам интерфейса.
Можно избежать конфликта имен и сделать, например, так.
Код C#
1
2
ICamera.CameraShoot();
IGun.GunShoot();
Но запись вида
Код C#
1
camera.CameraShoot();
тоже как-то не комильфо.
Ответ:
Сообщение от PlutDem
но стоит ли так делать?
Иногда вопрос звучит немного иначе: "А есть ли выбор"? (см. IEnumerable<T>)

Если вы только делаете архитектуру, то конечно попытайтесь избежать подобного, но только в том случае, если это не вредит семантике. Если вредит — не запаривайтесь, это вполне нормальная практика.

Кстати, в вашем примере как раз-таки лучше оставить метод Shoot и предоставлять явную реализацию интерфейсов, т.к. метод Shoot наиболее подходящий.
Вопрос: Вызов методов классов по указателям

Имеется управляющий класс, в котором определен указатель на функцию:
Код C++
1
void (Operation*) ();
Как передавать по данному указателю методы классов? Что-то вроде:
Код C++
1
func(&MyClass1::method1);
Разумеется:
Код C++
1
2
3
4
class MyClass1 {
public:
void method1(); 
}
Вообще можно ли так сделать?
Ответ: ответ прежний. два варианта. см. выше. с std::function писанины будет меньше. туда можно будет засовывать свободные функции, методы разных классов, и лямбды. сигнатура при этом одна останется.
Вопрос: Интерфейс для работы с структурами данных

Есть интерфейс, который выводит информацию о структуре данных.

Java
1
2
3
4
5
6
7
8
public interface DataStructureInfo {
    public int findAverage();
    public int findMin();
    public int findMax();
    public int fourthElement();
    public int preMinElement();
    public void printInfo();
}
Под каждую структуру данных есть отдельный класс. Когда я реализую метод интерфейса в классе, мне нужно передать в качестве аргумента структуру данных(Queue, Stack и тд). Как в самом интерфейсе, в параметрах методов, указать что туда могут передаваться различные структуры данных, а не одна конкретная?
Ответ:
Сообщение от Artmal
Ну двусвязный список это LinkedList
да, я ошибся. Имел в виду односвязанный.
Похоже вы не до конца поняли задание а уже хотите его делать. В джава все коллекции имлементируют интерфейс Collection. Вам всего лишь надо написать класс который принимает на вход такой Collection и делает всё необходимое. Ваш интерфейс из первого поста ни к чему.
Вопрос: Зачем в Java нужно переопределение методов интерфейса?

Например, есть 2 интерфейса: DataOutput и ObjectOutput. ObjectOutout наследует DataOutput, и "переопределяет" некоторые методы, в частности public void write(int b) throws IOException;
Зачем нужно переопределять методы в интерфейсе - наследнике, если реализации все равно нет никакой - это же интерфейс.
Спасибо заранее
Ответ: turbanoff, но его как такового может и не быть, тогда ловить его не обязательно. Это странно