LINUX.ORG.RU

C++ и Java: от кого травма?

 ,


0

2

В Java есть ключевое слово final и в C++ есть похожее ключевое слово const. В Java со всеми объектами работают только через ссылки на них, в C++ это является лишь одной из возможностей. В Java final ссылка на объект означает лишь то, что нельзя менять саму ссылку, но если объект мутабельный, можно менять его состояние. По наивности я думал, что в C++ всё примерно так же, но оказалось, что совсем не так.

Для начала простой пример на Java

public class MainClass {
    private static void foo(final StringBuilder stringBuilder) {
        stringBuilder.append("#foo()");
        System.out.println(stringBuilder);
    }

    public static void main(String[] args) {
        foo(new StringBuilder("Hello from MainClass"));
    }
}

Этот код изменяет содержимое stringBuilder и после этого печатает Hello from MainClass#foo()

Теперь перейдём к коду на C++

#include <iostream>
#include <string>

void foo(std::string& str) {
	str.append("foo()");
	std::cout << str << std::endl;
}


int main() {
	std::string str{"Hello from "};
	foo(str);
	return 0;
}

В этом коде функция foo() так же получает ссылку на стринговый объект, изменяет содержимое этого объекта не меняя саму ссылку и печатает результат: Hello from foo(). Но стоит добавить ключевое слово const перед объявлением этой ссылки в аргументах функции foo() и код перестаёт компилироваться из-за неожиданного отсутствия append().

Среди Java разработчиков попадаются и бывшие сишники. Обычно их можно обнаружить по некоторым привычкам из C/C++. Например по 5 == n, что для Java совершенно бесполезно, поскольку int не кастится в boolean и соответственно ошибочно написанное if (n = 5) приведёт к ошибке компиляции, как и if (5 = n) в C/C++. Так вот в некоторых компаниях Java разработчиков заставляют (например через maven-checkstyle-plugin) объявлять все аргументы публичных методов как final, что совершенно глупо и только раздражает. Сейчас у меня появилось предположение, что это пришло от покусанных C++ бывших сишников.

Так от какого же языка травма?



Последнее исправление: zg (всего исправлений: 2)

Ответ на: комментарий от zg

В связи с ограничениями тогдашнего железа в языке C пошли на массу компромисов.

Он такой убогий был не из за железа, а потому что была такая цель, сделать минимальную систему.

MOPKOBKA ★★★★
()
Ответ на: комментарий от zg

though with a syntax based somewhat on C++

Я про это же и писал: на семантику Modula-2 натянули синтаксис от C++, чтобы свитчеры не пугались. У Java есть двоюродный брат - Golang, можешь на него посмотреть.

LongLiveUbuntu ★★★★★
()

никакого смысла использование final переменных и аргументов не имеет, скорее даже наоборот:

  • код получается более громоздким из-за необходимости объявлять новые переменные, несущие тот же смысл (яркий пример: проход по дереву вверх до достижения какого-то условия)
  • начинаются извращения с использованием к месту и не к месту тернарного оператора и «лямб»

оно имело определенный смысл, когда за переменной прятался ресурс, который нужно было обязательно закрывать и здесь использование final защищало от обидных ошибок, но try-with-resources эту проблему убрал

borisych ★★★★★
()
Ответ на: комментарий от borisych

никакого смысла использование final переменных и аргументов не имеет, скорее даже наоборот:

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

LongLiveUbuntu ★★★★★
()
Ответ на: комментарий от LongLiveUbuntu

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

Какое отношение immutable объекты имеют к слову final у переменной или аргументов метода? Никакого.

borisych ★★★★★
()

Еще D посмотри там вообще сплошная транзитивная иммутабельность https://dlang.org/articles/const-faq.html и кроме const еще есть immutable. Хотя C++ в последних стандартах уже почти все оттуда передрал, но исторически там все-равно все гораздо мягче.

anonymous
()
Ответ на: комментарий от witaway

Вроде фича маст-хев, но видел её полноценно пока только в плюсах и хрусте. Может ещё где-то есть?

Вся функцинальщина на этом стоит, OCaml и другие ML, haskell и т. п..

anonymous
()
Ответ на: комментарий от witaway

Я просто ощущаю, что после if-а семантика переменной самую-самую капельку меняется. Это два очень похожих, но разных по смыслу объекта. Они вполне могут иметь два разных имени.

В rust или OCaml они вполне могут иметь и одинаковое имя, там разрешается затенение (shadowing):

fn main(){
    let val = 10;
    println!("val = {}", val);    // val = 10
    let val = val + 15;   // используем ранее определенную переменную val
    println!("val = {}", val);    // val = 25
    let val: String = val.to_string() + "1"; // другой тип и val ="251"
    println!("val = {}", val);
}

anonymous
()